/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "core/shader_built_in_functions.h"
#include "core/动画/curve.h"
#include "core/属性.h"
#include "core/shader_std.h"
#include "core/空间划分/球形八叉树.h"

#include "../Mesh.h"
#include "../面.h"

#include "引擎数据类型.h"


#include <matXX.h>
#include <随机数.h>
#include <字符串/str_分割.h>





static S_多边形元素* f_多边形桥接边(S_多边形& poly,
	                       const uvec2* edgeA_ptr, 
                           const uvec2* edgeB_ptr,
	                       uint32 数量max,
	                       uint32 数量min
) {
	vec3* vert = poly.m_顶点.data();
	
	S_多边形元素* 多边形面索引 = (S_多边形元素*)f_core_array_new(0, sizeof(S_面*));
	
	if (vert) {
		float32 步进0 = 0;
		float32 步进1 = 0;

		for (uint32 i = 0; i < 数量max; ++i) {
			步进0 += vec_len(vert[edgeA_ptr[i].y] - vert[edgeA_ptr[i].x]);
		}
		for (uint32 i = 0; i < 数量min; ++i) {
			步进1 += vec_len(vert[edgeB_ptr[i].y] - vert[edgeB_ptr[i].x]);
		}
		//以配对遮罩.push_back(edgeB_ptr[数量min-1].y);


		float32 长度比例 = 步进1 / 步进0;
		步进0 = 0;
		步进1 = 0;

		uint32 对边顶点索引 = 0;
		uint32 跨行 = 0;
		for (uint32 i = 0; i < 数量max; ++i) {
			S_面* 多边形面 = new S_面((S_结构指针)&poly);
			多边形面->材质槽 = 0;

			uvec2 new_edgeA;
			uvec2 new_edgeB;

			S_边* 边 = new S_边;
			边->polygon = (S_结构指针)&poly;

			new_edgeA.x = edgeA_ptr[i].x;
			new_edgeA.y = edgeB_ptr[对边顶点索引].x;

			new_edgeB.x = edgeA_ptr[i].y;
			new_edgeB.y = edgeB_ptr[对边顶点索引].y;


			//多边形面->vertIndex.push_back(edgeA_ptr[i].x);
			//多边形面->vertIndex.push_back(edgeA_ptr[i].y);
			多边形面->vertIndex.emplace_back(edgeA_ptr[i].x);
			多边形面->vertIndex.emplace_back(edgeA_ptr[i].y);


			步进0 += vec_len(vert[edgeA_ptr[i].y] - vert[edgeA_ptr[i].x]);
			assert(对边顶点索引 < 数量min);
			if (步进1 < 步进0 * 长度比例) {

				步进1 += vec_len(vert[edgeB_ptr[对边顶点索引].y] - vert[edgeB_ptr[对边顶点索引].x]);

				//边->edge.push_back(new_edgeA);
				//边->edge.push_back(new_edgeB);
				边->edge.emplace_back(new_edgeA);
				边->edge.emplace_back(new_edgeB);

				//多边形面->vertIndex.push_back(edgeB_ptr[对边顶点索引].y);
				//多边形面->vertIndex.push_back(edgeB_ptr[对边顶点索引].x);
				多边形面->vertIndex.emplace_back(edgeB_ptr[对边顶点索引].y);
				多边形面->vertIndex.emplace_back(edgeB_ptr[对边顶点索引].x);

				if (对边顶点索引 + 1 < 数量min) ++对边顶点索引;
				++跨行;
			}
			else {
				if (跨行 >= 数量min) {
					边->edge.push_back(new_edgeB);

					new_edgeB = { edgeB_ptr[对边顶点索引].y , new_edgeA.x };
					边->edge.push_back(new_edgeB);
					//多边形面->vertIndex.push_back(edgeB_ptr[对边顶点索引].y);
					多边形面->vertIndex.emplace_back(edgeB_ptr[对边顶点索引].y);
					
				}
				else {
					多边形面->vertIndex.emplace_back(edgeB_ptr[对边顶点索引].x);
					//多边形面->vertIndex.push_back(edgeB_ptr[对边顶点索引].x);
					//多边形面->vertIndex.push_back(new_edgeA.x);
				}
				if (对边顶点索引 < 数量min) {

				}
			}

			多边形面->edge.push_back(poly.m_边_过时成员.size());
			poly.m_边_过时成员.push_back(边);

			f_core_array_push_back((S_Array*)多边形面索引, (uint8*)&多边形面);
			多边形面->ID = poly.m_面.size();
			poly.m_面.push_back(多边形面);
		}

		for (auto& e : poly.m_面自定义属性) {
			f_core_array_resize(e.second, poly.m_面.size());
		}
	}
	
	return 多边形面索引;
}



static void f_多边形桥接点(const vec3* 多数边顶点, const vec3* 少数边顶点, uint32 数量max, uint32 数量min, S_UI32Array* indexs, S_uVec2Array* loop) {
	uint32 index = 0;
	uvec2 环 = {};


	uint32 对边顶点索引 = 0;
	uint32 跨行 = 数量max;
	--数量max;
	--数量min;
	
	float32 步进0 = 0;
	float32 步进1 = 0;

	for (uint32 i = 0; i < 数量max; ++i) {
		步进0 += vec_len(多数边顶点[i] - 多数边顶点[i + 1]);
	}
	for (uint32 i = 0; i < 数量min; ++i) {
		步进1 += vec_len(少数边顶点[i] - 少数边顶点[i + 1]);
	}


	float32 长度比例 = 步进1 / 步进0;
	步进0 = 0;
	步进1 = 0;
	for (uint32 i = 0; i < 数量max; ++i) {

		index = i;
		f_core_array_push_back((S_Array*)indexs, (uint8*)&index);
		++index;
		f_core_array_push_back((S_Array*)indexs, (uint8*)&index);

		assert(对边顶点索引 <= 数量min);
		步进0 += vec_len(多数边顶点[i + 1] - 多数边顶点[i]);
		

		if (步进1 < 步进0 * 长度比例 && 对边顶点索引 < 数量min) {
			float32 l = vec_len(少数边顶点[对边顶点索引 + 1] - 少数边顶点[对边顶点索引]);
			步进1 += l;

			++对边顶点索引;
			index = 跨行 + 对边顶点索引;
			f_core_array_push_back((S_Array*)indexs, (uint8*)&index);

			--index;
			f_core_array_push_back((S_Array*)indexs, (uint8*)&index);

			环.y = 4;
		}
		else {
			index = 跨行 + 对边顶点索引;
			f_core_array_push_back((S_Array*)indexs, (uint8*)&index);

			环.y = 3;
		}
		
		loop->ptr_userData[i] = 环;
		环.x += 环.y;
	}

}




S_多边形* f_surface_创建多边形() {
	S_多边形* 多边形 = new S_多边形;
	多边形->m_元素组 = (S_多边形元素Array*)f_core_array_new(0, sizeof(S_多边形元素*), false);
	return 多边形;
}

void f_surface_清除多边形元素(S_多边形* 多边形) {
//#pragma omp parallel sections
//	{
//#pragma omp section
//		{
			uint32 num = 多边形->m_边_过时成员.size();
			auto* edge = 多边形->m_边_过时成员.data();
			for (int32 i = 0; i < num; ++i) {
				delete edge[i];
			}
//		}
//#pragma omp section
//		{
			num = 多边形->m_面.size();
			auto* face = 多边形->m_面.data();
			for (int32 i = 0; i < num; ++i) {
				delete face[i];
			}
//		}
//	}

#pragma omp parallel for num_threads(DEF_Min(8, 多边形->m_元素组->count))
	for (int64 i = 0; i < 多边形->m_元素组->count; ++i) {
		f_core_array_free((S_Array*)多边形->m_元素组->ptr_userData[i]);
	}
	f_core_array_resize((S_Array*)多边形->m_元素组, 0);


	多边形->m_UV索引.clear();
	多边形->m_顶点.clear();
	多边形->m_法线.clear();
	多边形->m_UV.clear();
	
	多边形->m_边_过时成员.clear();
	多边形->m_面.clear();

	多边形->m_UV层数量 = 0;

	if (多边形->m_点自定义属性.size()) {
		for (auto& e : 多边形->m_点自定义属性) {
			f_core_array_free(e.second);
		}
	}
	
	for (auto& e : 多边形->m_面自定义属性) {
		f_core_array_free(e.second);
	}

	多边形->m_点自定义属性.clear();
	多边形->m_面自定义属性.clear();
}

void f_surface_销毁多边形(S_多边形* 多边形) {
	f_surface_清除多边形元素(多边形);
	f_core_array_free((S_Array*)多边形->m_元素组);
	delete 多边形;
}

S_多边形元素* f_surface_多边形桥接(S_多边形* poly, const S_边& edgeA, const S_边& edgeB) {
	uint32 numA = edgeA.edge.size();
	uint32 numB = edgeB.edge.size();
	if (!numA || !numB) return nullptr;

	S_多边形元素* 面索引 = nullptr;

	poly = (S_多边形*)edgeA.polygon;

	vec3* vert = poly->m_顶点.data();
	auto* edgeA_ptr = edgeA.edge.data();
	auto* edgeB_ptr = edgeB.edge.data();

	/*vec3 全局方向A = {};
	for (uint32 i = 0; i < numA; ++i) {
		vec_add(&全局方向A, vert[edgeA_ptr[i].y] - vert[edgeA_ptr[i].x]);
	}
	vec3 全局方向B = {};
	for (uint32 i = 0; i < numB; ++i) {
		vec_add(&全局方向B, vert[edgeB_ptr[i].y] - vert[edgeB_ptr[i].x]);
	}
	vec_normalize(&全局方向A);
	vec_normalize(&全局方向B);


	
	if (vec_dot(全局方向A, 全局方向B) >= 0) {
		面索引 = f_多边形桥接边(poly, edgeA_ptr, edgeB_ptr, numA, numB);
	}
	else {
		面索引 = f_多边形桥接边(poly, edgeA_ptr, edgeB_ptr, numA, numB);
	}*/

	uint32 数量max = DEF_Max(numA, numB);
	uint32 数量min = DEF_Min(numA, numB);
	

	if (numA >= numB) {
		面索引 = f_多边形桥接边(*poly, edgeA_ptr, edgeB_ptr, numA, numB);
	}
	else {
		面索引 = f_多边形桥接边(*poly, edgeB_ptr, edgeA_ptr, numB, numA);
	}

	f_core_array_push_back((S_Array*)poly->m_元素组, (uint8*)&面索引);
	return 面索引;
}

S_Vec3Array* f_surface_点桥接(const S_Vec3Array* a, const S_Vec3Array* b, S_UI32Array* indexs, S_uVec2Array* loop) {
	uint32 numA = a->count;
	uint32 numB = b->count;

	S_Vec3Array* vert = (S_Vec3Array*)f_core_array_new(0, sizeof(vec3));
	if (!numA || !numB) return vert;

	uint32 数量max = DEF_Max(numA, numB);
	uint32 数量min = DEF_Min(numA, numB);
	--numA;
	--numB;
	

	/*vec3 全局方向A = {};
	for (uint32 i = 0; i < numA; ++i) {
		vec_add(&全局方向A, a->ptr_userData[i+1] - a->ptr_userData[i]);
	}
	vec3 全局方向B = {};
	for (uint32 i = 0; i < numB; ++i) {
		vec_add(&全局方向B, b->ptr_userData[i + 1] - b->ptr_userData[i]);
	}
	vec_normalize(&全局方向A);
	vec_normalize(&全局方向B);

	
	if (vec_dot(全局方向A, 全局方向B) >= 0) {
		
	}
	else {
		
	}*/
	

	const vec3* 多数边;
	const vec3* 少数边;
	if (numA >= numB) {
		多数边 = a->ptr_userData;
		少数边 = b->ptr_userData;

		f_core_array_append((S_Array*)vert, (S_Array*)a);
		f_core_array_append((S_Array*)vert, (S_Array*)b);
	}
	else {
		多数边 = b->ptr_userData;
		少数边 = a->ptr_userData;

		f_core_array_append((S_Array*)vert, (S_Array*)b);
		f_core_array_append((S_Array*)vert, (S_Array*)a);
	}

	f_core_array_resize((S_Array*)loop, 数量max - 1);
	f_core_array_resize((S_Array*)indexs, 0);
	f_多边形桥接点(多数边, 少数边, 数量max, 数量min, indexs, loop);

	
	return vert;
}



static Inline float32 f_面角度大小(const vec3* vert, const uvec3& index, const vec3& 法线) {
	vec3 左边 = vert[index.x];
	vec3 中间 = vert[index.y];
	vec3 右边 = vert[index.z];

	vec3 v1 = vec_normalize(右边 - 中间);
	vec3 v2 = vec_normalize(中间 - 左边);
	
	return vec_dot(v1, v2) + 1.0;
	float32 dt = vec_dot(vec_cross(v1, v2), 法线);
	if (dt >= 0) {
		dt = vec_dot(v1, v2) + 1.0;
		return dt;
	}
	return -1;
}

static int32 f_分割出一个三角形(const vec3* vert, const vec3& 面法线, uint32* index, uint32 num, uvec3* 当前三角形顶点) {
	float32 d = 0;
	int32 当前选中顶点 = -1;
	for (uint32 i = 0; i < num; ++i) {
		uvec3 三角形;
		三角形.x = i;
		三角形.y = i + 1;
		三角形.z = i + 2;

		if (三角形.y >= num) {
			三角形.y = 三角形.y - num;
		}
		if (三角形.z >= num) {
			三角形.z = 三角形.z - num;
		}
		int32 id = 三角形.y;
		

		uvec3 临时三角形索引;
		临时三角形索引.x = index[三角形.x];
		临时三角形索引.y = index[三角形.y];
		临时三角形索引.z = index[三角形.z];


		float32 dt = f_面角度大小(vert, 临时三角形索引, 面法线);
		if (dt > d) {
			d = dt;
			当前三角形顶点[0] = 临时三角形索引;
			当前三角形顶点[1] = 三角形;

			当前选中顶点 = id;
		}
	}

	return 当前选中顶点;
}

void f_mesh_多边形三角化(S_Mesh* me, const S_多边形* 多边形) {
	std::vector<uvec3> 三角形索引;
	std::vector<uvec3> 纹理坐标索引[8];
	std::vector<bool> 面平直;
	std::vector<S_FaceElement> 面;


	std::map<std::u16string, S_Array*> 面自定义属性;
	std::map<std::u16string, S_Array*> 点自定义属性;
	for (auto& e : 多边形->m_点自定义属性) {
		点自定义属性[e.first] = f_core_array_new_type(0, f_core_array_getType(e.second));
	}
	for (auto& e : 多边形->m_面自定义属性) {
		面自定义属性[e.first] = f_core_array_new_type(0, f_core_array_getType(e.second));
	}


	uint32 num = 多边形->m_面.size();
	auto* face = 多边形->m_面.data();
	auto* vert = 多边形->m_顶点.data();
	auto* uvIndex = 多边形->m_UV索引.data();


	三角形索引.reserve(num*2);
	for (uint32 i = 0; i < 8; ++i) {
		纹理坐标索引[i].reserve(num*2);
	}
	面平直.reserve(num*2);
	面.reserve(num*2);


	
	f_core_array_reserve((S_Array*)me->m_材质槽ID, 0);
	

	for (uint32 i = 0; i < num; ++i) {
		auto tmpIndex = face[i]->vertIndex;
		auto tmpUvLoop = face[i]->uvLoopIndex;
		bool 面是否平直 = face[i]->面平直;
		int32 材质槽 = face[i]->材质槽;

		uint32 uvNum = tmpUvLoop.size();
		uint32 面顶点数量 = tmpIndex.size();
		if(面顶点数量 < 3) continue;

		auto face_ptr = tmpIndex.data();


		std::vector<uint32> tmpUVIndex[8];
		vec3 dir0;

		#pragma omp parallel sections
		{
			#pragma omp section
			{
				//计算中点
				vec3 中点{};
				for (uint32 j = 0; j < 面顶点数量; ++j) {
					中点 += vert[face_ptr[j]];
				}
				中点 /= num;
		
				dir0 = vec_normalize(中点 - vert[face_ptr[0]]);
				vec3 dir1 = vec_normalize(vert[face_ptr[1]] - 中点);
				dir0 = vec_normalize(vec_cross(dir0, dir1));
			}
			#pragma omp section
			{
				for (uint32 j = 0; j < uvNum; ++j) {
					uvec2 UV全局索引区间 = tmpUvLoop[j];
					for (uint32 k = UV全局索引区间.x; k < UV全局索引区间.y; ++k) {
						tmpUVIndex[j].push_back(uvIndex[k]);
					}
				}
			}
		}

		


		uint32 分解面顶点数量 = tmpIndex.size();
		for (uint32 j = 0; j < 分解面顶点数量; ) {
			face_ptr = tmpIndex.data();
			
			uvec3 分割纹理坐标索引{};

			if (分解面顶点数量 <= 3) {
				uvec3 ti{ face_ptr[0], face_ptr[1], face_ptr[2] };
				三角形索引.emplace_back(ti);
				面平直.emplace_back(面是否平直);
				面.push_back({ int32(面是否平直), 0, 材质槽, DEF_OBTYPE_Mesh, 0xffffffff });
				//if(材质槽 == 1 || 材质槽 == 0) 
				//	std::cout<<std::endl;
				f_core_array_push_back((S_Array*)me->m_材质槽ID, (uint8*)&材质槽);

				if (uvNum) {
					auto* uv_ptr = tmpUvLoop.data();
					for (uint32 uv层 = 0; uv层 < uvNum; ++uv层) {
						uint32 num = tmpUVIndex[uv层].size();
						if (num) {
							分割纹理坐标索引.x = tmpUVIndex[uv层][0];
							分割纹理坐标索引.y = tmpUVIndex[uv层][1 < num ? 1 : 0];
							分割纹理坐标索引.z = tmpUVIndex[uv层][2 < num ? 2 : 0];
						}
						纹理坐标索引[uv层].emplace_back(分割纹理坐标索引);
					}
				}
				else {
					纹理坐标索引[0].emplace_back(分割纹理坐标索引);
				}


				//自定义属性
				for (auto& e : 多边形->m_面自定义属性) {
					f_core_array_push_back(面自定义属性[e.first], f_core_array_at(e.second, i));
				}

				break;
			}

			//顶点和UV索引
			uvec3 当前三角形顶点局部偏移[2];
			int32 当前选中顶点 = f_分割出一个三角形(vert, dir0, face_ptr, 分解面顶点数量, 当前三角形顶点局部偏移);

			if (当前选中顶点 >= 0) {
				
				#pragma omp parallel sections
				{
					#pragma omp section
					{
						if (uvNum) {
							for (uint32 uv层 = 0; uv层 < uvNum; ++uv层) {
								uint32 num = tmpUVIndex[uv层].size();
								if (num) {
									分割纹理坐标索引.x = tmpUVIndex[uv层][当前三角形顶点局部偏移[1].x < num ? 当前三角形顶点局部偏移[1].x : 0];
									分割纹理坐标索引.y = tmpUVIndex[uv层][当前三角形顶点局部偏移[1].y < num ? 当前三角形顶点局部偏移[1].y : 0];
									分割纹理坐标索引.z = tmpUVIndex[uv层][当前三角形顶点局部偏移[1].z < num ? 当前三角形顶点局部偏移[1].z : 0];
									
									if (当前选中顶点 < num) {
										tmpUVIndex[uv层].erase(tmpUVIndex[uv层].begin() + 当前选中顶点);
									}
								}
								纹理坐标索引[uv层].emplace_back(分割纹理坐标索引);
							}
						}
						else {
							纹理坐标索引[0].emplace_back(分割纹理坐标索引);
						}
					}
					#pragma omp section
					{
						三角形索引.emplace_back(当前三角形顶点局部偏移[0]);
						面平直.emplace_back(面是否平直);
						面.push_back({ int32(面是否平直), 0, 材质槽, DEF_OBTYPE_Mesh, 0xffffffff });
						f_core_array_push_back((S_Array*)me->m_材质槽ID, (uint8*)&材质槽);

						//自定义属性
						for (auto& e : 多边形->m_面自定义属性) {
							f_core_array_push_back(面自定义属性[e.first], f_core_array_at(e.second, i));
						}

						//移除选中顶点索引
						tmpIndex.erase(tmpIndex.begin() + 当前选中顶点);
						分解面顶点数量 = tmpIndex.size();
						j = 0;
					}
				}
			}
			else {
				++j;
			}
		}
	}
	
	
	if (三角形索引.size()) {
		me->f_填充索引数据(sizeof(uvec3), 三角形索引.size(), (void*)三角形索引.data());
		
	}
	else {
		me->f_Clear();
		me->f_Clear索引();
	}
	

	
	//f_surface_fill面平滑模式(me, 面平直);
	

	for (auto& e : 点自定义属性) {
		auto& attr = *me->m_点自定义属性区间偏移;
		attr[e.first] = f_surface_填充自定义属性(me, e.second, 1);
	}
	for (auto& e : 面自定义属性) {
		auto& attr = *me->m_面自定义属性区间偏移;
		attr[e.first] = f_surface_填充自定义属性(me, e.second, 1);
	}

	f_bm_resize(*me->m_自定义属性索引, DEF_网格自定义属性槽数量* DEF_网格自定义属性槽数量);
	for (uint32 i = 0; i < DEF_网格自定义属性槽数量 * DEF_网格自定义属性槽数量; ++i) {
		f_buf_属性索引_at(*me->m_自定义属性索引, i) = {};
	}
	
	
	f_surface_fill纹理坐标索引(me, 纹理坐标索引);
	f_surface_fill层纹理坐标(me, 多边形->m_UV);
	f_mesh_fill面(me, 面);
}

std::vector<vec2> f_mesh_get多边形网格UV(S_Mesh* mesh, const S_多边形* 多边形) {
	uint32 num = 多边形->m_顶点.size();
	std::vector<vec2> UV(num);

	auto uvIndex = 多边形->m_UV索引.data();
	auto uvCoord = 多边形->m_UV.data();

	for (auto& f : 多边形->m_面) {
		uint32 vNum = f->vertIndex.size();
		uvec2 uvRange{};

		if (f->uvLoopIndex.empty() == false) {
			uvRange = f->uvLoopIndex[0];
		}

		for (uint32 i = 0; i < uvRange.y; ++i) {
			uint32 index = f->vertIndex[i];
			UV[index] = uvCoord[uvIndex[uvRange.x + i]];
		}
	}

	return UV;
}



void f_surface_合并顶点(S_多边形* 多边形, float32 最大距离) {
	std::vector<S_Sphere> 包围盒;
	f_surface_计算三角形球体包围盒(多边形, 包围盒);
}



void f_surface_计算平滑法线(S_多边形* 多边形) {
	std::vector<S_Sphere> 包围盒;
	f_surface_计算三角形球体包围盒(多边形, 包围盒);
}

void f_surface_计算三角形球体包围盒(S_多边形* 多边形, std::vector<S_Sphere>& 包围盒) {
	auto 顶点 = 多边形->m_顶点.data();
	auto 索引 = 多边形->m_面.data();

	uint32 num = 多边形->m_面.size();
	包围盒.resize(num);
	auto* 球 = 包围盒.data();
	
#pragma omp parallel for
	for (int32 i = 0; i < num; ++i) {
		auto face_ptr = 索引[i]->vertIndex.data();
		uint16 face_num = 索引[i]->vertIndex.size();

		//计算中点
		vec3 中点{};
		for (uint32 j = 0; j < face_num; ++j) {
			中点 += 顶点[face_ptr[j]];
		}
		中点 /= num;

		索引[i]->面中心 = 中点;

		int32 maxLenID = 0;
		float32 maxLen = 0;
		for (uint32 j = 0; j < face_num; ++j) {
			float32 len = vec_len(中点 - 顶点[face_ptr[j]]);
			if (len > maxLen) {
				len = maxLen;
				maxLen = j;
			}
		}
		球[i].pos = 中点;
		球[i].radius = maxLen;

	}

}



S_多边形元素* f_surface_边网格化(S_多边形* 多边形, S_边& 边, S_边& 倒角) {
	uint32 num = 边.edge.size();
	--num;

	auto* edge_ptr = 边.edge.data();
	for (uint32 i = 0; i < num; ++i) {

	}
	//S_多边形面* face = f_surface_多边形桥接(多边形, 倒角, 倒角);
	return nullptr;
}

float32 f_surface_边长度(S_边& 边, vec3* vert) {
	uint32 num = 边.edge.size();
	auto edge_pr = 边.edge.data();
	float32 len = 0;
	for (uint32 i = 0; i < num; ++i) {
		len += vec_len(vert[edge_pr[i].y] - vert[edge_pr[i].x]);
	}
	return len;
}

float32 f_surface_2D边长度(const S_Vec2Array* vert) {
	int32 num = vert->count - 1;
	float32 len = 0;
	for (uint32 i = 0; i < num; ++i) {
		len += vec_len(vert->ptr_userData[i + 1] - vert->ptr_userData[i]);
	}
	return len;
}

float32 f_surface_3D边长度(const S_Vec3Array* vert) {
	int32 num = vert->count - 1;
	float32 len = 0;
	for (uint32 i = 0; i < num; ++i) {
		len += vec_len(vert->ptr_userData[i + 1] - vert->ptr_userData[i]);
	}
	return len;
}

void f_surface_边多点采样(S_边* 边,
	                 const vec2& 区间, 
					 float32 偏移,

	                float32 最小间隔,
	                float32 随机间隔,
	                float32 随机种子,
	                
	                
	                S_Vec3Array* 采样返回坐标, 
	                S_Vec3Array* 采样返回向量
					//, bool 变换
	) {

	if(!边 || !边->polygon) return;
	S_多边形* 多边形 = (S_多边形*)边->polygon;

	uint32 num = 边->edge.size();
	
	f_core_array_clear((S_Array*)采样返回坐标);
	f_core_array_clear((S_Array*)采样返回向量);

	if (num) {
		auto edge_ptr = 边->edge.data();
		vec3* vert_ptr = 多边形->m_顶点.data();

		float32 len = f_surface_边长度(*边, vert_ptr);
		float32 步进 = 0;

		vec2 步进区间;
		步进区间.x = 区间.x * len;
		步进区间.y = 区间.y * len;



		最小间隔 = DEF_Max(最小间隔, 0.0001);
		随机间隔 = DEF_Max(随机间隔, 0);
		float32 当前步进 = 偏移;
		for (uint32 i = 0; i < num; ++i) {
			vec3 线向量 = vert_ptr[edge_ptr[i].y] - vert_ptr[edge_ptr[i].x];
			float32 当前线段长度 = vec_normalize(&线向量);


			if (当前线段长度 > 0) {
				while (当前步进 < 当前线段长度) {
					vec3 采样坐标 = 线向量 * 当前步进 + vert_ptr[edge_ptr[i].x];

					float32 当前全局步进 = 步进 + 当前步进;
					if (当前全局步进 >= 步进区间.x && 当前全局步进 <= 步进区间.y) {
						//if (变换) {
						//	
						//}

						f_core_array_push_back((S_Array*)采样返回坐标, (uint8*)&采样坐标);
						f_core_array_push_back((S_Array*)采样返回向量, (uint8*)&线向量);
					}

					随机种子 += i + 1;
					当前步进 += (f_random_F32(随机种子) * 随机间隔);
					当前步进 += (最小间隔);

					if (当前步进 > 当前线段长度 || 当前步进 > 10000) // || 当前步进 <= INFINITE
						break;
				}
			}

			当前步进 -= 当前线段长度;
			//处理多余步进部分
			步进 += 当前线段长度;

			当前步进 = DEF_Max(当前步进, 0);

		}

		vec3 末尾坐标 = vert_ptr[edge_ptr[num - 1].y];
		vec3 末尾向量 = vec_normalize(末尾坐标 - vert_ptr[edge_ptr[num - 1].x]);

		f_core_array_push_back((S_Array*)采样返回坐标, (uint8*)&末尾坐标);
		f_core_array_push_back((S_Array*)采样返回向量, (uint8*)&末尾向量);
	}

}

void f_surface_边采样(S_边* 边, const vec2& 区间, float32 偏移, vec3& 采样返回坐标, vec3& 采样返回向量) {

	if (!边 || !边->polygon) return;
	S_多边形* 多边形 = (S_多边形*)边->polygon;

	uint32 num = 边->edge.size();
	auto edge_ptr = 边->edge.data();
	vec3* vert_ptr = 多边形->m_顶点.data();

	float32 len = f_surface_边长度(*边, vert_ptr);
	if(偏移 < 区间.x) {
		采样返回坐标 = num ? vert_ptr[edge_ptr[0].x] : vec3{};
		
		采样返回向量 = {};
		return;
	}
	if (偏移 > 区间.y) {
		采样返回坐标 = num ? vert_ptr[edge_ptr[num-1].y] : vec3{};
		
		采样返回向量 = {};
		return;
	}


	偏移 *= len;

	float32 步进 = 0;
	//float32 当前步进 = 偏移;
	for (uint32 i = 0; i < num; ++i) {
		vec3 线向量 = vert_ptr[edge_ptr[i].y] - vert_ptr[edge_ptr[i].x];
		float32 当前线段长度 = vec_normalize(&线向量);

		if (步进 + 当前线段长度 >= 偏移) {
			当前线段长度 = 步进 + 当前线段长度 - 偏移;

			采样返回坐标 = vert_ptr[edge_ptr[i].y] - 线向量 * 当前线段长度;
			采样返回向量 = 线向量;
			break;
		}

		步进 += 当前线段长度;
	}

}

void f_surface_以点采样边(
	const S_Vec3Array* 端点坐标,
	const vec2& 区间,
	float32 最小间隔,
	float32 随机间隔,
	float32 随机种子,
	bool 归一化,
	//float32 偏移,

	S_Vec3Array* 采样返回坐标,
	S_Vec3Array* 采样返回向量
) {
	float32 len = f_surface_3D边长度(端点坐标);
	uint32 num = 端点坐标->count;

	float32 步进 = 0;

	vec2 步进区间;
	步进区间.x = 区间.x * len;
	步进区间.y = 区间.y * len;

	f_core_array_clear((S_Array*)采样返回坐标);
	f_core_array_clear((S_Array*)采样返回向量);


	最小间隔 = DEF_Max(最小间隔, 0);
	随机间隔 = DEF_Max(随机间隔, 0);
	float32 当前步进 = 0;
	for (uint32 i = 0; i < num; ++i) {
		vec3 线向量 = 端点坐标->ptr_userData[i+1] - 端点坐标->ptr_userData[i];
		float32 当前线段长度 = vec_normalize(&线向量);


		if (当前线段长度 > 0) {
			while (当前步进 < 当前线段长度) {
				vec3 采样坐标 = 线向量 * 当前步进 + 端点坐标->ptr_userData[i];

				float32 当前全局步进 = 步进 + 当前步进;
				if (当前全局步进 >= 步进区间.x && 当前全局步进 <= 步进区间.y) {
					f_core_array_push_back((S_Array*)采样返回坐标, (uint8*)&采样坐标);
					f_core_array_push_back((S_Array*)采样返回向量, (uint8*)&线向量);
				}

				随机种子 += i + 1;
				当前步进 += (f_random_F32(随机种子) * 随机间隔);
				当前步进 += (最小间隔);

				if (当前步进 > 当前线段长度 || 当前步进 > 10000) // || 当前步进 <= INFINITE
					break;
			}
		}

		当前步进 -= 当前线段长度;
		//处理多余步进部分
		步进 += 当前线段长度;

		当前步进 = DEF_Max(当前步进, 0);

	}

	vec3 末尾坐标 = 端点坐标->ptr_userData[num];
	vec3 末尾向量 = vec_normalize(末尾坐标 - 端点坐标->ptr_userData[num]);

	f_core_array_push_back((S_Array*)采样返回坐标, (uint8*)&末尾坐标);
	f_core_array_push_back((S_Array*)采样返回向量, (uint8*)&末尾向量);
}

void f_surface_线段方向(const S_Vec3Array* 端点坐标, S_Vec3Array* 采样返回向量) {

	uint32 num = 端点坐标->count;
	f_core_array_resize((S_Array*)采样返回向量, num);

	--num;
	if(!num) return;

	for (uint32 i = 0; i < num; ++i) {
		vec3 线向量 = 端点坐标->ptr_userData[i + 1] - 端点坐标->ptr_userData[i];
		采样返回向量->ptr_userData[i] = normalize(线向量);
	}
	采样返回向量->ptr_userData[num] = 采样返回向量->ptr_userData[num - 1];
}

S_多边形元素* f_surface_复制(S_多边形* poly, S_多边形元素* 要复制的面元素, const vec3& loc, const vec3& rot, const vec3& scal, uint8 合并元素) {
	
	auto 新建面数量 = 要复制的面元素->count;
	if(!新建面数量) return nullptr;

	const auto* faceIndex_ptr = 要复制的面元素->ptr_userData;
	uint32 已有面数量 = poly->m_面.size();
	uint32 当前顶点数量 = poly->m_顶点.size();

	std::map<uint32, uint32> 新顶点索引映射;
	std::vector<uint32> 新顶点索引;
	
	std::vector<vec3> 新顶点;
	std::vector<vec3> 新法线;
	std::vector<vec2> 新UV;
	std::vector<S_边*> 新边;

	
	auto mat = f_mat44_构建XYZ变换矩阵({loc, rot, scal});
	auto rotMat = f_mat44_构建XYZ变换矩阵({{}, rot, {1,1,1}});
	
	S_多边形元素* 元素 = (S_多边形元素*)f_core_array_new(0, sizeof(S_面*));
	
	S_Array* 顶点拷贝索引 = (S_Array*)f_core_array_new_type(0, E_值类型::e_Type_UI32_1D);
	S_Array* 面点拷贝索引 = (S_Array*)f_core_array_new_type(0, E_值类型::e_Type_UI32_1D);

	S_面** face_ptr = nullptr;
	vec3* vert_ptr = nullptr;
	vec3* normal_ptr = nullptr;
	//vec2* uv_ptr = nullptr;

	//std::mutex 内存锁;


	uint32 顶点索引偏移 = 0;
	for (uint32 i = 0; i < 新建面数量; ++i) {
		S_面* 多边形面 = new S_面((S_结构指针)poly);
		//多边形面->polygon = (S_结构对象指针)poly;

		S_多边形* 源多边形 = (S_多边形*)faceIndex_ptr[i]->polygon;
		face_ptr = 源多边形->m_面.data();
		vert_ptr = 源多边形->m_顶点.data();
		normal_ptr = 源多边形->m_法线.data();
		//uv_ptr = 源多边形->m_UV.data();


		auto* 源顶点索引 = faceIndex_ptr[i]->vertIndex.data();
		auto indexNum = faceIndex_ptr[i]->vertIndex.size();

		多边形面->vertIndex.reserve(indexNum);

		for (uint32 j = 0; j < indexNum; ++j) {
			uint32 当前面顶点索引 = 源顶点索引[j];

			if (合并元素) {
				if (新顶点索引映射.find(当前面顶点索引) == 新顶点索引映射.end()) {
					多边形面->vertIndex.emplace_back(当前顶点数量 + 顶点索引偏移);

					新顶点索引映射[当前面顶点索引] = 顶点索引偏移;
					++顶点索引偏移;
				}
				else {
					多边形面->vertIndex.emplace_back(当前顶点数量 + 新顶点索引映射[当前面顶点索引]);
				}
			}
			else {
				多边形面->vertIndex.push_back(新顶点.size() + 当前顶点数量);

				新顶点.push_back(mat * vert_ptr[当前面顶点索引]);
				新法线.push_back(rotMat * normal_ptr[当前面顶点索引]);
				//新UV.push_back(uv_ptr[]);
			}
			f_core_array_push_back(顶点拷贝索引, (uint8*)&当前面顶点索引);
		}

		多边形面->uvLoopIndex = faceIndex_ptr[i]->uvLoopIndex;
		多边形面->edge = faceIndex_ptr[i]->edge;
		多边形面->材质槽 = faceIndex_ptr[i]->材质槽;
		多边形面->ID = 已有面数量 + i;
		

		f_core_array_push_back(面点拷贝索引, (uint8*)&多边形面->ID);
		f_core_array_push_back((S_Array*)元素, (uint8*)&多边形面);
		poly->m_面.emplace_back(多边形面);
	}
	
	if (合并元素 && 新建面数量) {
		新顶点.resize(顶点索引偏移);
		新法线.resize(顶点索引偏移);
		for (auto& e : 新顶点索引映射) {
			新顶点[e.second] = mat * vert_ptr[e.first];
			新法线[e.second] = rotMat * normal_ptr[e.first];
		}
	}
	

	poly->m_顶点.insert(poly->m_顶点.end(), 新顶点.begin(), 新顶点.end());
	poly->m_法线.insert(poly->m_法线.end(), 新法线.begin(), 新法线.end());
	//poly->m_UV.insert(poly->m_UV.end(), 新UV.begin(), 新UV.end());
	//poly->m_面.insert(poly->m_面.end(), 新面.begin(), 新面.end());
	f_core_array_push_back((S_Array*)poly->m_元素组, (uint8*)&元素);


	for (auto& e : poly->m_点自定义属性) {
		f_core_array_resize(e.second, poly->m_顶点.size());
		f_core_array_区间自拷贝(e.second, (S_UI32Array*)顶点拷贝索引, 当前顶点数量);
	}
	for (auto& e : poly->m_面自定义属性) {
		f_core_array_resize(e.second, poly->m_面.size());
		f_core_array_区间自拷贝(e.second, (S_UI32Array*)面点拷贝索引, 已有面数量);
	}


	return 元素;
}

void f_surface_多边形元素变换(S_多边形元素* 面元素, const vec3& loc, const vec3& rot, const vec3& scal) {
	if(!面元素->count) return;

	auto num = 面元素->count;
	auto* faceIndex_ptr = 面元素->ptr_userData;

	S_多边形* 多边形 = (S_多边形*)(faceIndex_ptr[0]->polygon);
	auto* vert = 多边形->m_顶点.data();
	auto* normal = 多边形->m_法线.data();

	auto mat_loc = f_mat44_构建XYZ变换矩阵({ loc, rot, scal });
	auto mat_rot = f_mat44_构建XYZ变换矩阵({ {}, rot, scal});


	std::vector<uint32> 索引;
	for (uint32 i = 0; i < num; ++i) {
		索引.insert(索引.end(), faceIndex_ptr[i]->vertIndex.begin(), faceIndex_ptr[i]->vertIndex.end());
	}
	std::sort(索引.begin(), 索引.end());
	索引.erase(unique(索引.begin(), 索引.end()), 索引.end());


	uint32 pointNum = 索引.size();
	auto* index = 索引.data();
	for (uint32 i = 0; i < pointNum; ++i) {
		uint32 vertIndex = index[i];
		vert[vertIndex] = mat_loc * vert[vertIndex];
		normal[vertIndex] = mat_rot * normal[vertIndex];
	}
}

void f_surface_多边形元素组变换(S_多边形元素Array* 面元素, const S_Vec3Array* loc, const S_Vec3Array* rot, const S_Vec3Array* scal) {
	auto num = 面元素->count;

	bool 移动多例 = loc->count >= num;
	bool 旋转多例 = rot->count >= num;
	bool 缩放多例 = scal->count >= num;

	for (uint32 i = 0; i < num; ++i) {
		vec3& l = 移动多例 ? loc->ptr_userData[i] : loc->ptr_userData[0];
		vec3& r = 旋转多例 ? rot->ptr_userData[i] : rot->ptr_userData[0];
		vec3& s = 缩放多例 ? scal->ptr_userData[i] : scal->ptr_userData[0];

		if (面元素->ptr_userData[i]) {
			f_surface_多边形元素变换(面元素->ptr_userData[i], l, r, s);
		}
	}
}

void f_surface_多边形变换(S_多边形* self, const vec3& loc, const vec3& rot, const vec3& scal) {
	auto num = self->m_顶点.size();

	auto* point = self->m_顶点.data();
	auto* normal = self->m_法线.data();


	auto mat_loc = f_mat44_构建XYZ变换矩阵({ loc, rot, scal });
	auto mat_rot = f_mat44_构建XYZ变换矩阵({ {}, rot, scal});

	for (uint32 i = 0; i < num; ++i) {
		point[i] = mat_loc * point[i];
		normal[i] = mat_rot * normal[i];
	}
}

S_多边形Array* f_surface_复制多边形(S_多边形* 源, const vec3& loc, const vec3& rot, const vec3& scal) {
	return nullptr;
}

S_多边形Array* f_surface_拷贝多边形(const S_多边形Array* 源, S_多边形Array* 目标, const S_Vec3Array* loc, const S_Vec3Array* rot, const S_Vec3Array* scal) {
	uint32 num = 目标->count;
	S_多边形Array* ploy = (S_多边形Array*)f_core_array_new(num, sizeof(S_多边形*));

	bool 多源 = 源->count >= num;
	bool 移动多例 = loc->count >= num;
	bool 旋转多例 = loc->count >= num;
	bool 缩放多例 = loc->count >= num;

	
	//auto mat = f_mat44_构建XYZ变换矩阵({loc, rot, scal});
	for (uint32 i = 0; i < num; ++i) {
		//auto 目标多边形 = 目标->ptr_userData[i];
		
		S_多边形* 源多边形;
		if (多源) {
			源多边形 = 源->ptr_userData[i];
		}
		else {
			源多边形 = 源->ptr_userData[0];
		}

		if (!源多边形 || !目标->ptr_userData[i]) continue;

		vec3 移动;
		if(移动多例) 移动 = loc->ptr_userData[i];
		else 移动 = loc->ptr_userData[0];
		vec3 旋转;
		if (旋转多例) 旋转 = rot->ptr_userData[i];
		else 旋转 = rot->ptr_userData[0];
		vec3 缩放;
		if (缩放多例) 缩放 = scal->ptr_userData[i];
		else 缩放 = scal->ptr_userData[0];

		f_surface_copy(源多边形, 目标->ptr_userData[i]);

		f_surface_多边形变换(目标->ptr_userData[i], 移动, 旋转, 缩放);

		ploy->ptr_userData[i] = 目标->ptr_userData[i];
	}

	return ploy;
}

//void f_surface_释放元素(S_多边形* self, S_多边形元素* 面元素) {
//	delete 面元素;
//}

void f_surface_释放元素组(S_多边形* self, S_多边形元素Array* 面元素) {
	for (uint32 i = 0; i < 面元素->count; ++i) {
		delete 面元素->ptr_userData[i];
	}
	f_core_array_free((S_Array*)面元素);
}

S_多边形元素Array* f_surface_线实体化(S_边Array* 边, S_Vec3Array* 倒角, S_F32Array* 半径, const S_曲线& curve, int32 节点类型, int32 半径迭代方式) {
	S_多边形元素Array* 元素组 = (S_多边形元素Array*)f_core_array_new(0, sizeof(S_多边形元素*));

	switch (节点类型) {
		case 0:{
			S_Vec3Array* newVert = (S_Vec3Array*)f_core_array_new(0, sizeof(vec3));

			for (uint32 i = 0; i < 边->count; ++i) {
				if(!边->ptr_userData[i]) continue;
				int32 段数量 = 边->ptr_userData[i]->edge.size() - 1;
				if(段数量 < 0) continue;


				S_多边形* 多边形 = (S_多边形*)边->ptr_userData[i]->polygon;
				auto* vert = 多边形->m_顶点.data();
				auto* 点索引 = 边->ptr_userData[i]->edge.data();


				
				std::vector<vec4> q; q.reserve(段数量 + 2);
				std::vector<vec3> v; v.reserve(段数量 + 2);
				std::vector<float32> 长度步进;

				float32 总长度 = 0;
				for (uint32 k = 0; k <= 段数量; ++k) {
					auto L = 点索引[k];
					vec3 v1 = (vert[L.y] - vert[L.x]);
					总长度 += vec_len(v1);

					长度步进.push_back(总长度);
				}
				长度步进.push_back(总长度);


				q.push_back(f_graph_quat两向量(normalize(vert[点索引[0].y] - vert[点索引[0].x]), { 0, 1, 0 }));
				v.push_back(vert[点索引[0].x]);
				for (uint32 k = 0; k < 段数量; ++k) {
					auto L = 点索引[k];
					auto R = 点索引[k+1];

					vec3 v1 = normalize(vert[L.y] - vert[L.x]);
					vec3 v2 = normalize(vert[R.y] - vert[R.x]);
					//vec3 中点 = (v2 - v1) * 0.5;
					vec3 法线 = vec_cross(v1, v2);
					vec3 旋转朝向 = vec_cross(法线, v2 + v1);


					//q.push_back(f_graph_quat两向量((v2 - v1), { 0, 1, 0 }));
					q.push_back(f_graph_quat两向量(normalize(v1 + v2) , { 0, 1, 0 }));
					v.push_back(vert[L.y]);
				}
				q.push_back(f_graph_quat两向量((vert[点索引[段数量].y] - vert[点索引[段数量].x]), { 0, 1, 0 }));
				v.push_back(vert[点索引[段数量].y]);


				
				++段数量;
				std::vector<S_边*> 新边; 新边.reserve(段数量 + 2);
				float32 s = 0;
				for (uint32 k = 0; k <= 段数量; s = 长度步进[k] / 总长度, ++k) {
					f_core_array_copy((S_Array*)newVert, (S_Array*)倒角);

					s = f_graph_钳制曲线采样(s, curve, {0,1});
					for (uint32 d = 0; d < newVert->count; ++d) {
						newVert->ptr_userData[d] = (f_graph_quatTranformInv(q[k], 倒角->ptr_userData[d] * s) + v[k]);
						//newVert->ptr_userData[d] = f_graph_quatTranform(q[k], newVert->ptr_userData[d]) + v[k];
					}
					uvec2 vr = f_surface_添加多边形顶点(多边形, newVert, {});
					auto* 边 = f_surface_添加多边形边(多边形, vr, 1, 0);
					if(边) 新边.push_back(边);

				}
				
				段数量 = int32(新边.size()) - 1;
				for (int32 k = 0; k < 段数量; ++k) {
					S_多边形元素* e = f_surface_多边形桥接(多边形, *新边[k], *新边[k+1]);
					f_core_array_push_back((S_Array*)元素组, (uint8*)&e);
				}
				
			}

			f_core_array_free((S_Array*)newVert);
			break;
		}
		case 1: {
			break;
		}
		default:
			break;
	}

	return 元素组;
}

//void f_surface_销毁多边形元素(S_多边形元素* 面组) {
//	delete 面组;
//}



uvec2 f_surface_添加多边形顶点(S_多边形* self, S_Vec3Array* verts, S_Vec3Array* normal) {
	if(!self) return {};

	auto& m_多边形 = *(self);

	uvec2 r;
	r.x = m_多边形.m_顶点.size();
	r.y = verts->count;

	if (m_多边形.m_顶点.size() > 50000000) return {};

	m_多边形.m_法线.resize(r.x + r.y);
	m_多边形.m_顶点.resize(r.x + r.y);
	
	if (normal) {

	}

	vec3* 顶点坐标 = m_多边形.m_顶点.data();

	for (auto& e : m_多边形.m_点自定义属性) {
		f_core_array_resize(e.second, r.x + r.y);
	}

	for (uint32 i = 0; i < r.y; ++i) {
		顶点坐标[i + r.x] = verts->ptr_userData[i];
	}


	return r;
}

uvec2 f_surface_添加多边形法线(S_多边形* 多边形, S_Vec3Array* verts) {
	uvec2 r;
	r.x = 多边形->m_法线.size();
	r.y = verts->count;

	多边形->m_法线.resize(r.x + r.y);
	auto* 法线 = 多边形->m_法线.data();

	for (uint32 i = 0; i < r.y; ++i) {
		法线[i + r.x] = verts->ptr_userData[i];
	}

	return r;
}

uvec2 f_surface_添加多边形纹理坐标(S_多边形* 多边形, const S_Vec2Array* uv, const S_UI32Array* indexs, S_uVec2Array* 环) {
	//uvec2 r;
	uint32 已有UV顶点偏移 = 多边形->m_UV.size();
	uint32 新UV数量 = uv->count;
	//r.y = verts->count;
	

	多边形->m_UV.resize(已有UV顶点偏移 + 新UV数量);
	auto* UV坐标 = 多边形->m_UV.data();

	
	for (uint32 i = 0; i < 新UV数量; ++i) {
		UV坐标[i + 已有UV顶点偏移] = uv->ptr_userData[i];
	}



	uint32 新索引数量 = indexs->count;
	uint32 UV索引偏移 = 多边形->m_UV索引.size();

	if (indexs) {
		新索引数量 = indexs->count;

		UV索引偏移 = 多边形->m_UV索引.size();
		多边形->m_UV索引.resize(UV索引偏移 + 新索引数量);
		auto* UV索引 = 多边形->m_UV索引.data();

		for (uint32 i = 0; i < 新索引数量; ++i) {
			UV索引[i + UV索引偏移] = DEF_Min(indexs->ptr_userData[i], 新UV数量) + 已有UV顶点偏移;
		}


		新索引数量 += UV索引偏移;
		for (uint32 i = 0; i < 环->count; ++i) {
			环->ptr_userData[i].x = DEF_Min(环->ptr_userData[i].x + UV索引偏移, 新索引数量 - 1);
			环->ptr_userData[i].y = 新索引数量;
		}
	}
	else {
		新索引数量 = 新UV数量;

		UV索引偏移 = 多边形->m_UV索引.size();
		多边形->m_UV索引.resize(UV索引偏移 + 新索引数量);
		auto* UV索引 = 多边形->m_UV索引.data();

		for (uint32 i = 0; i < 新索引数量; ++i) {
			UV索引[i + UV索引偏移] = i + 已有UV顶点偏移;
		}



		新索引数量 += UV索引偏移;
		for (uint32 i = 0; i < 环->count; ++i) {
			环->ptr_userData[i].x = DEF_Min(环->ptr_userData[i].x + UV索引偏移, 新索引数量 - 1);
			环->ptr_userData[i].y = 新索引数量;
		}
	}
	

	

	return { 已有UV顶点偏移, 新UV数量 };
}

void f_surface_设置边形顶点法线(S_多边形* 多边形, S_Vec3Array* verts, uint32 offset) {
	多边形->m_法线;
}

S_边* f_surface_添加多边形边(S_多边形* self, uvec2 offset, int32 线模式, int32 渲染模式) {
	if (offset.y < 2 || offset.x > 100000000) return nullptr;

	auto& m_多边形 = *(self);

	S_边* edge = new S_边;
	edge->polygon = (S_结构指针)self;

	switch (线模式) {
		case 0: {
			uint32 num = offset.y - 1;
			for (uint32 i = 0; i < num; ++i) {
				uvec2 e;
				e.x = offset.x + i;
				e.y = offset.x + i + 1;
				edge->edge.push_back(e);
			}
			break;
		}
		case 1: {
			uint32 num = offset.y - 1;
			for (uint32 i = 0; i < num; ++i) {
				uvec2 e;
				e.x = offset.x + i;
				e.y = offset.x + i + 1;
				edge->edge.push_back(e);
			}

			uvec2 e;
			e.x = offset.x + num;
			e.y = offset.x;
			edge->edge.push_back(e);
		
			break;
		}
		case 2: {
			uint32 num = offset.y / 2;
			for (uint32 i = 0; i < num; ++i) {
				uvec2 e;
				e.x = i * 2;
				e.y = i * 2 + 1;
				edge->edge.push_back(e + offset.x);
			}
			break;
		}
	}



	edge->渲染模式 = 渲染模式;
	switch (渲染模式) {
		case 0: {
			break;
		}
		case 1: {
			break;
		}
		default:
			break;
	}
	
	m_多边形.m_边_过时成员.push_back(edge);
	return edge;
}

S_面* f_surface_添加多边形面(S_多边形* poly, uint32* index, uint32 num, uint32 offset) {
	S_面* 多边形面 = new S_面((S_结构指针)poly);
	S_边* edge = new S_边;

	多边形面->polygon = (S_结构指针)poly;
	edge->polygon = (S_结构指针)poly;

	多边形面->vertIndex.resize(num);
	for (uint32 i = 0; i < num; ++i) {
		多边形面->vertIndex[i] = index[i] + offset;
		多边形面->材质槽 = 0;

		uvec2 vert_range;
		if (i + 1 >= num) {
			vert_range = { index[num-1], index[0] };
		}
		else {
			vert_range = { index[i], index[i + 1] };
		}
		vert_range += offset;
		edge->edge.push_back(vert_range);
		
	}
	多边形面->ID = poly->m_面.size();

	poly->m_边_过时成员.push_back(edge);
	poly->m_面.push_back(多边形面);

	for (auto& e : poly->m_面自定义属性) {
		f_core_array_resize(e.second, poly->m_面.size());
	}
	return 多边形面;
}

S_多边形元素* f_surface_添加多边形元素(S_多边形* poly, S_Vec3Array* 顶点, S_UI32Array* 索引, S_uVec2Array* 环) {
	uint32 面数量 = 环->count;
	if (!面数量 && 索引->count) {
		面数量 = 1;
	}

	S_多边形元素* 多边形元素 = (S_多边形元素*)f_core_array_new(0, sizeof(S_面*));

	uint32 索引数量 = 索引->count;
	uint32 新顶点数量 = 顶点->count;
	uint32 顶点开始偏移 = poly->m_顶点.size();
	uint32 边开始偏移 = poly->m_边_过时成员.size();
	poly->m_顶点.resize(顶点开始偏移 + 顶点->count);
	auto* vert = poly->m_顶点.data();
	for (uint32 i = 0; i < 新顶点数量; ++i) {
		vert[i + 顶点开始偏移] = 顶点->ptr_userData[i];
	}

	uint32 面开始偏移 = poly->m_面.size();
	poly->m_面.resize(面开始偏移 + 面数量);


	新顶点数量 = poly->m_顶点.size();
	顶点开始偏移;
	if (环->count) {
		for (uint32 i = 0; i < 面数量; ++i) {
			uvec2 r = 环->ptr_userData[i];
			r.y = DEF_Min(r.y, 索引数量);
			r.x = DEF_Min(r.x, 索引数量);


			S_面* 多边形面 = new S_面((S_结构指针)poly);
			//多边形面->polygon = (S_结构对象指针)poly;

			多边形面->vertIndex.resize(r.y);
			
			for (uint32 j = 0; j < r.y; ++j) {
				uint32 index = DEF_Min(索引->ptr_userData[r.x + j] + 顶点开始偏移, 新顶点数量);
				多边形面->vertIndex[j] = index;
			}
			//多边形元素->面索引.push_back(面开始偏移 + i);
			f_core_array_push_back((S_Array*)多边形元素, (uint8*)&多边形面);
			poly->m_面[面开始偏移 + i] = 多边形面;



			S_边* 边 = new S_边;
			if (r.y) {
				--(r.y);
				边->edge.resize(r.y);
				for (uint32 j = 0; j < r.y; ++j) {
					uvec2 r = { 多边形面->vertIndex[j], 多边形面->vertIndex[j + 1] };
					边->edge[j] = r;
				}
				边->edge[r.y] = { 多边形面->vertIndex[r.y], 多边形面->vertIndex[0] };
			}
			


			多边形面->edge.push_back(poly->m_边_过时成员.size());
			poly->m_边_过时成员.push_back(边);

		}
	}
	else {
		//多边形元素->面索引.push_back(面开始偏移);
		S_面* 多边形面 = new S_面((S_结构指针)poly);
		//多边形面->polygon = (S_结构对象指针)poly;

		for (uint32 i = 0; i < 索引数量; ++i) {
			多边形面->vertIndex[i] = DEF_Min(索引->ptr_userData[i] + 顶点开始偏移, 新顶点数量);
		}
		poly->m_面[面开始偏移] = 多边形面;
		f_core_array_push_back((S_Array*)多边形元素, (uint8*)&多边形面);
	}
	
	f_core_array_push_back((S_Array*)poly->m_元素组, (uint8*)&多边形元素);

	for (auto& e : poly->m_面自定义属性) {
		f_core_array_resize(e.second, poly->m_面.size());
	}
	return 多边形元素;
}

S_多边形元素* f_surface_从区间索引构建多边形面(S_多边形* poly, uvec2 index, uvec2 UV环, uint32 uv层, bool 面朝向) {
	S_面* 面 = new S_面((S_结构指针)poly);
	S_多边形元素* 多边形元素 = (S_多边形元素*)f_core_array_new(0, sizeof(S_面*));

	uint32 num = index.y;
	if (num) {
		uint32 IndexOffset = 面->vertIndex.size();

		面->vertIndex.resize(IndexOffset + num);
		if (面朝向) {
			for (uint32 i = 0; i < num; ++i) {
				面->vertIndex[i + IndexOffset] = index.x + i;
			}
		}
		else {
			uint32 offset = num + index.x - 1;
			for (int32 i = 0; i < num; ++i) {
				面->vertIndex[IndexOffset + i] = offset - i;
			}
		}


		if (uv层 >= 面->uvLoopIndex.size()) {
			面->uvLoopIndex.push_back({});
			uv层 = 面->uvLoopIndex.size() - 1;
		}
		面->uvLoopIndex[uv层] = UV环;


		面->ID = poly->m_面.size();
		//多边形元素->面索引.push_back(poly->m_面.size());
		f_core_array_push_back((S_Array*)多边形元素, (uint8*)&面);
		poly->m_面.push_back(面);

		for (auto& e : poly->m_面自定义属性) {
			f_core_array_resize(e.second, poly->m_面.size());
		}
	}
	
	f_core_array_push_back((S_Array*)poly->m_元素组, (uint8*)&多边形元素);
	return 多边形元素;
}

void f_surface_从元素中构建多边形(S_多边形* self, S_多边形* 新多边形, uint32 元素ID) {
	if (self->m_元素组->count) {
		S_多边形元素* 元素 = self->m_元素组->ptr_userData[元素ID];
		
		for (uint32 i = 新多边形->m_元素组->count; i < 1; ++i) {
			f_core_array_free((S_Array*)新多边形->m_元素组->ptr_userData[i]);
		}
		f_core_array_resize((S_Array*)新多边形->m_元素组, 1);


		uint32 最小顶点索引 = UINT_MAX;
		uint32 最大顶点索引 = 0;
		if (元素->count) {
			
			for (uint32 i = 0; i < 元素->count; ++i) {
				
				for (auto& e : 元素->ptr_userData[i]->vertIndex) {
					if (e < 最小顶点索引) 最小顶点索引 = e;
					if(e > 最大顶点索引) 最大顶点索引 = e;

				}

				std::max(元素->ptr_userData[i]->vertIndex.begin(), 元素->ptr_userData[i]->vertIndex.end());
			}
		}
	}
}

void f_poly_构建面(S_多边形* self, const S_边* 面) {
	//uint32 上一个顶点索引 = 面->edge.back().x;
	S_面* 多边形面 = new S_面((S_结构指针)&self);

	for (auto& e : 面->edge) {
		多边形面->vertIndex.push_back(e.x);
	}

	self->m_面.push_back(多边形面);
}

static bool f_项排序对比(const uvec2& ia, const uvec2& ib) {
	return (ia.y < ib.y);
}

void f_surface_排列多边形材质槽(S_多边形* self) {
	auto* face = self->m_面.data();
	uint32 num = self->m_面.size();

	if (num < 2) {
		return;
	}

	std::vector<uvec2> key(num);
//#pragma omp parallel for num_threads(DEF_Min(32, num))
	for (int32 i = 0; i < num; ++i) {
		key[i] = _uVec2(i, face[i]->材质槽);
		//face[i]->面平直 = 10;
	}
	std::sort(key.begin(), key.end(), f_项排序对比);


	auto faceTemp = self->m_面;
	auto attr_f = self->m_面自定义属性;
//#pragma omp parallel for num_threads(DEF_Min(32, num))
	for (auto& attr : attr_f) {
		attr.second = f_core_array_from(self->m_面自定义属性[attr.first]);
	}
	for (int32 i = 0; i < num; ++i) {
		self->m_面[i] = faceTemp[key[i].x];
	}

	for (auto& attr : attr_f) {
		num = attr.second->count;
		for (int32 i = 0; i < num; ++i) {
			f_core_array_元素复制(self->m_面自定义属性[attr.first], attr.second, i, key[i].x);
			//f_core_array_元素复制(self->m_面自定义属性[attr.first], attr.second, i, faceTemp[key[i].x]->ID);
			//f_core_array_元素复制(self->m_面自定义属性[attr.first], attr.second, i, self->m_面[i]->ID);
		}
	}
	

	for (auto& attr : attr_f) {
		f_core_array_free(attr.second);
	}
}

void f_surface_从索引构纹理面坐标(S_多边形* self, S_UI32Array* faceIndex, S_1DArray* uvIndex) {
	//self->m_面[faceIndex]->uvIndex;
}

void f_surface_取面索引(S_多边形* self, S_多边形元素* 面元素, S_1DArray* 索引) {
	uint32 old_num = 索引->count;
	if (!面元素 || !self) {
		for (uint32 i = 0; i < old_num; ++i) {
			free(索引->ptr_userData[i]);
		}
		return;
	}

	
	uint32 num = 面元素->count;
	for (uint32 i = num; i < old_num; ++i) {
		free(索引->ptr_userData[i]);
	}

	f_core_array_resize((S_Array*)索引, num);
	for (uint32 i = old_num; i < num; ++i) {
		索引->ptr_userData[i] = (S_Array*)malloc(sizeof(S_Array));
	}


	auto* faceIndex_ptr = 面元素->ptr_userData;
	for (uint32 i = 0; i < num; ++i) {
		auto* face = faceIndex_ptr[i];

		索引->ptr_userData[i]->ptr_userData = (uint8*)face->vertIndex.data();
		索引->ptr_userData[i]->count = face->vertIndex.size();
	}
}

void f_surface_取面顶点(const S_面* 面元素, S_Vec3Array* 顶点) {
	if(!面元素->polygon) return;
	auto p = *((S_多边形*)(面元素->polygon));
	uint32 num = 面元素->vertIndex.size();
	f_core_array_resize((S_Array*)顶点, num);

	auto* index_ptr = 面元素->vertIndex.data();
	auto* vert_ptr = ((S_多边形*)(面元素->polygon))->m_顶点.data();
	
	for (uint32 i = 0; i < num; ++i) {
		顶点->ptr_userData[i] = vert_ptr[index_ptr[i]];
	}
}

void f_surface_取面法线(const S_面* 面元素, S_Vec3Array* 法线) {
	if (!面元素->polygon) return;

	uint32 num = 面元素->vertIndex.size();
	f_core_array_resize((S_Array*)法线, num);

	auto* index_ptr = 面元素->vertIndex.data();
	auto* vert_ptr = ((S_多边形*)(面元素->polygon))->m_法线.data();

	for (uint32 i = 0; i < num; ++i) {
		法线->ptr_userData[i] = vert_ptr[index_ptr[i]];
	}
}

void f_surface_取面中心(const S_面* 面元素, S_Vec3Array* 中心) {
	if (!面元素->polygon) return;

	uint32 num = 面元素->vertIndex.size();
	f_core_array_resize((S_Array*)中心, 1);

	auto* index_ptr = 面元素->vertIndex.data();
	auto* vert_ptr = ((S_多边形*)(面元素->polygon))->m_顶点.data();

	vec3 重心{};
	for (uint32 i = 0; i < num; ++i) {
		重心 += vert_ptr[index_ptr[i]];
	}

	中心->ptr_userData[0] = 重心 / num;
}

void f_surface_取面顶点法线(const S_面* 面元素, S_Vec3Array* 法线) {
	if (!面元素->polygon) return;

	uint32 num = 面元素->vertIndex.size();
	f_core_array_resize((S_Array*)法线, num);

	auto* index_ptr = 面元素->vertIndex.data();
	auto* vert_ptr = ((S_多边形*)(面元素->polygon))->m_法线.data();

	for (uint32 i = 0; i < num; ++i) {
		法线->ptr_userData[i] = vert_ptr[index_ptr[i]];
	}
}


void f_surface_取面元素中心(const S_多边形元素* 面元素, S_Vec3Array* 中心) {
	uint32 num = 面元素->count;

	f_core_array_resize((S_Array*)中心, num);

	for (uint32 k = 0; k < num; ++k) {
		auto* 面 = 面元素->ptr_userData[k];

		uint32 面顶点索引数量 = 面->vertIndex.size();
		auto* index_ptr = 面->vertIndex.data();
		auto* vert_ptr = ((S_多边形*)(面->polygon))->m_顶点.data();

		vec3 重心{};
		for (uint32 i = 0; i < 面顶点索引数量; ++i) {
			重心 += vert_ptr[index_ptr[i]];
		}

		中心->ptr_userData[k] = 重心 / 面顶点索引数量;
	}
}
void f_surface_取多边形面中心(const S_多边形* 多边形, S_Vec3Array* 中心) {
	uint32 num = 多边形->m_面.size();

	f_core_array_resize((S_Array*)中心, num);

	for (uint32 k = 0; k < num; ++k) {
		auto* 面 = 多边形->m_面[k];

		uint32 面顶点索引数量 = 面->vertIndex.size();
		auto* index_ptr = 面->vertIndex.data();
		auto* vert_ptr = ((S_多边形*)(面->polygon))->m_顶点.data();

		vec3 重心{};
		for (uint32 i = 0; i < 面顶点索引数量; ++i) {
			重心 += vert_ptr[index_ptr[i]];
		}

		中心->ptr_userData[k] = 重心 / 面顶点索引数量;
	}
}


S_边* f_surface_取多边形边(const S_多边形* self, uint32 ID) {
	uint32 num = self->m_边_过时成员.size();
	if (ID < num) {
		return self->m_边_过时成员[ID];
	}
	else if (num) {
		return self->m_边_过时成员.back();
	}

	static S_多边形 多边形;
	static S_边 边{ (S_结构指针)&多边形, {}};
	return &边;
}

void f_surface_取多边形多个元素(S_多边形* self, S_UI32Array* 元素索引, S_多边形元素Array* 元素组) {
	f_core_array_resize((S_Array*)元素组, 0);

	uint32 总元素组数量 = self->m_元素组->count;
	for (uint32 i = 0; i < 元素索引->count; ++i) {
		uint32 index = 元素索引->ptr_userData[i];

		if (index < 总元素组数量) {
			f_core_array_push_back((S_Array*)元素组, (uint8*)&self->m_元素组->ptr_userData[index]);
		}
	}
}

S_多边形元素* f_surface_取多边形元素(S_多边形* self, uint32 元素索引) {
	if (self && 元素索引 < self->m_元素组->count) {
		return self->m_元素组->ptr_userData[元素索引];
	}
	//---------!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	static S_多边形元素* 元素 = (S_多边形元素*)f_core_array_new(0, sizeof(S_面*));
	return 元素;
}

S_面* f_surface_取多边形面(S_多边形元素* 面元素, uint32 index) {
	if (面元素 && index < 面元素->count && 面元素->count) {
		if (面元素->ptr_userData[index]) {
			return 面元素->ptr_userData[index];
		}
	}

	static S_面 空(0);
	return &空;
}

void f_surface_get元素索引(S_多边形* self, S_模型元素索引Array* a) {
	f_core_array_reserve((S_Array*)a, 0);

	uint32 num = self->m_元素组->count;

	std::vector<uint32> 全局偏移;
	uint32 offset = num;
	for (int32 i = 0; i < num; ++i) {
		S_多边形元素* 多边形元素 = self->m_元素组->ptr_userData[i];
		uint32 面数量 = 多边形元素->count;

		

		std::vector<uint32> 索引;
		索引.push_back(面数量);
		for (uint32 j = 0; j < 面数量; ++j) {
			索引.insert(索引.end(), 多边形元素->ptr_userData[j]->vertIndex.begin(), 多边形元素->ptr_userData[j]->vertIndex.end());
			
		}
		auto 相邻元素 = std::unique(索引.begin(), 索引.end());
		索引.erase(相邻元素, 索引.end());
		索引.insert(索引.begin(), 索引.size());
		f_core_array_push_back_block((S_Array*)a, (uint8*)索引.data(), 索引.size(), sizeof(uint32));
		f_core_array_CleanUnusedMemory((S_Array*)a);

		全局偏移.push_back(offset);
		offset += 索引.size();
	}
	f_core_array_push_front_block((S_Array*)a, (uint8*)全局偏移.data(), 全局偏移.size() * sizeof(uint32));
	f_core_array_CleanUnusedMemory((S_Array*)a);
}




void f_surface_设置面顶点(const S_面* 面元素, const S_Vec3Array* 顶点) {
	if (!面元素->polygon) return;

	uint32 num = 面元素->vertIndex.size();
	if(顶点->count < num || !num) return;

	auto* index_ptr = 面元素->vertIndex.data();
	auto* vert_ptr = ((S_多边形*)(面元素->polygon))->m_顶点.data();
	for (uint32 i = 0; i < num; ++i) {
		vert_ptr[index_ptr[i]] = 顶点->ptr_userData[i];
	}
}

void f_surface_设置面顶点法线(const S_面* 面元素, const S_Vec3Array* 法线) {
	if (!面元素->polygon) return;

	uint32 num = 面元素->vertIndex.size();
	if (法线->count < num || !num) return;

	auto* index_ptr = 面元素->vertIndex.data();
	auto* normal_ptr = ((S_多边形*)(面元素->polygon))->m_法线.data();
	for (uint32 i = 0; i < num; ++i) {
		normal_ptr[index_ptr[i]] = 法线->ptr_userData[i];
	}
}

void f_surface_设置面法线(const S_面* 面元素, const S_Vec3Array* 法线) {
}

void f_surface_设置面中心(const S_面* 面元素, const S_Vec3Array* 中心) {
}


void f_surface_设置元素UV环(S_多边形* self, S_多边形元素* 元素, S_uVec2Array* 环, uint32 uv层) {
	if (元素) {
		uint32 面数量 = 元素->count;
		auto* 面索引 = 元素->ptr_userData;

		bool 环单例 = 环->count < 面数量;
		for (uint32 i = 0; i < 面数量; ++i) {
			
			if (uv层 >= 面索引[i]->uvLoopIndex.size()) {
				self = (S_多边形*)面索引[i]->polygon;

				面索引[i]->uvLoopIndex.resize(DEF_Min(uv层 + 1, 8));
				self->m_UV层数量 = DEF_Max(self->m_UV层数量, uv层);
			}

			if (环单例) 面索引[i]->uvLoopIndex[uv层] = 环->ptr_userData[0];
			else 面索引[i]->uvLoopIndex[uv层] = 环->ptr_userData[i];
		}
	}
}

void f_surface_设置元素组UV环(S_多边形* self, S_多边形元素Array* 元素组, S_uVec2Array* 环, uint32 uv层) {
	uint32 num = 元素组->count;

	for (uint32 i = 0; i < num; ++i) {
		uint32 num = 元素组->count;
		f_surface_设置元素UV环(self, 元素组->ptr_userData[i], 环, uv层);
	}
}

void f_surface_设置元素材质槽ID(S_多边形* self, const S_多边形元素* 元素, S_UI32Array* 槽ID) {
	

	uint32 num = 元素->count;
	auto* faceIndex_ptr = 元素->ptr_userData;
	if (num && faceIndex_ptr[0] == nullptr) return;

	bool in1单例 = 槽ID->count < num;


	for (uint32 i = 0; i < num; ++i) {
		if(in1单例) faceIndex_ptr[i]->材质槽 = 槽ID->ptr_userData[0];
		else faceIndex_ptr[i]->材质槽 = 槽ID->ptr_userData[i];
	}
}

void f_surface_设置元素组材质槽ID(S_多边形* self, const S_多边形元素Array* 元素, S_UI32Array* 槽ID) {
	uint32 num = 元素->count;
	
#pragma omp parallel for num_threads(DEF_Min(8, 元素->count))
	for (int32 j = 0; j < 元素->count; ++j) {
		S_多边形元素* 面组 = 元素->ptr_userData[j];
		if(!面组) continue;

		uint32 num = 面组->count;
		bool in1单例 = 槽ID->count < num;

		auto* faceIndex_ptr = 面组->ptr_userData;
		
		for (uint32 i = 0; i < num; ++i) {
			if (in1单例) faceIndex_ptr[i]->材质槽 = 槽ID->ptr_userData[0];
			else faceIndex_ptr[i]->材质槽 = 槽ID->ptr_userData[j];
		}
	}
}


void f_surface_设置面平滑模式(S_面* 面, bool 平直) {
	S_多边形& self = *(S_多边形*)面->polygon;
	面->面平直 = 平直;
}

void f_surface_设置元素平滑模式(const S_多边形元素* 元素, S_BoolArray* 平直) {
	bool 多例 = 平直->count >= 元素->count;

	for (uint32 j = 0; j < 元素->count; ++j) {
		if (多例) {
			f_surface_设置面平滑模式(元素->ptr_userData[j], 平直->ptr_userData[j]);
		}
		else {
			f_surface_设置面平滑模式(元素->ptr_userData[j], 平直->ptr_userData[0]);
		}
	}
}

void f_surface_设置元素组平滑模式(const S_多边形元素Array* 元素组, S_BoolArray* 平直) {

#pragma omp parallel for num_threads(DEF_Min(16, 元素组->count))
	for (int32 j = 0; j < 元素组->count; ++j) {
		if(元素组->ptr_userData[j]) f_surface_设置元素平滑模式(元素组->ptr_userData[j], 平直);
	}
}


void f_surface_构建多边形边网格(S_Mesh* me, const std::vector<S_边*>& 边) {
	uint32 边组数量 = 边.size();

	std::vector<uint32> 顶点边索引;
	for (uint32 i = 0; i < 边组数量; ++i) {
		uint32 边数量 = 边[i]->edge.size();

		auto edge = 边[i]->edge.data();
		for (uint32 j = 0; j < 边数量; ++j) {
			顶点边索引.push_back(edge[j].x);
			顶点边索引.push_back(edge[j].y);
		}
	}

	f_me_fill索引(me, 顶点边索引);
}

void f_surface_构建线网格(S_Mesh* me, const std::vector<S_边*>& 边) {
	auto* edge = 边.data();
	uint32 num = 边.size();

	std::vector<uint32> index;
	for (uint32 i = 0; i < num; ++i) {
		switch (edge[i]->渲染模式) {
			case 1: {
				uint32 线段数量 = edge[i]->edge.size();
				auto* 线段索引 = edge[i]->edge.data();

				for (uint32 x = 0; x < 线段数量; ++x) {
					if (x) {
						index.push_back(线段索引[x-1].y);
					}
					else {
						index.push_back(线段索引[x].x);
					}

					index.push_back(线段索引[x].x);
					index.push_back(线段索引[x].y);

					if (x+1 >= 线段数量) {
						index.push_back(线段索引[x].y);
					}
					else {
						index.push_back(线段索引[x+1].x);
					}

					index.push_back(0xffffffff);
				}
				break;
			}
		}
	}

	f_me_fill索引(me, index);
}

S_多边形元素* f_surface_构建预设多边形(S_多边形* poly, const uvec3& 细分, const vec3& 大小, uint8 类型) {

	std::vector<vec3> 顶点;
	std::vector<vec3> 法线;
	std::vector<vec2> UV;
	std::vector<uint32> 索引;
	std::vector<uvec2> 边索引;

	bool 三角化 = false;

	uvec2 球体经纬{};
	switch (类型) {
	case 0:
		f_graph_构建平面(*(vec2*)((float32*)&大小), *(uvec2*)((uint32*)&细分), 顶点, 法线, UV, 索引, 边索引, false);
		break;
	case 1:
		球体经纬 = f_graph_构建球体(细分.x, 细分.y, 大小.x, 顶点, 法线, UV, 索引, false);
		break;
	case 2:
		f_graph_构建立方体(大小, 细分, 顶点, 法线, UV, 索引, false);
		break;
	default:
		break;
	}

	uint32 index_offset = poly->m_顶点.size();

	
	uint32 num = 索引.size();
	auto index_ptr = 索引.data();

	S_多边形元素* 面组 = (S_多边形元素*)f_core_array_new(0, sizeof(S_面*));
	switch (类型) {
	case 1: {
		uint32 offset = 0;
		for (uint32 x = 0; x < 球体经纬.x; ++x) {
			auto face = f_surface_添加多边形面(poly, &index_ptr[offset], 3, poly->m_顶点.size());
			f_core_array_push_back((S_Array*)面组, (uint8*)&face);
			offset += 3;
			
		}
		if (三角化) {
			for (uint32 y = 1; y < 球体经纬.y - 1; ++y) {
				for (uint32 x = 0; x < 球体经纬.x; ++x) {
					auto face = f_surface_添加多边形面(poly, &index_ptr[offset], 3, poly->m_顶点.size());
					f_core_array_push_back((S_Array*)面组, (uint8*)&face);
					offset += 4;
				}
			}
		}
		else {
			for (uint32 y = 1; y < 球体经纬.y - 1; ++y) {
				for (uint32 x = 0; x < 球体经纬.x; ++x) {
					auto face = f_surface_添加多边形面(poly, &index_ptr[offset], 4, poly->m_顶点.size());
					f_core_array_push_back((S_Array*)面组, (uint8*)&face);
					offset += 4;
				}
			}
		}

		for (uint32 x = 0; x < 球体经纬.x; ++x) {
			auto face = f_surface_添加多边形面(poly, &index_ptr[offset], 3, poly->m_顶点.size());
			f_core_array_push_back((S_Array*)面组, (uint8*)&face);
			offset += 3;
			
		}
		break;
	}
	default: {
		if (三角化) {
			for (uint32 i = 0; i < num; i += 3) {
				auto face = f_surface_添加多边形面(poly, &index_ptr[i], 3, poly->m_顶点.size());
				f_core_array_push_back((S_Array*)面组, (uint8*)&face);
			}
		}
		else {
			for (uint32 i = 0; i < num; i += 4) {
				auto face = f_surface_添加多边形面(poly, &index_ptr[i], 4, poly->m_顶点.size());
				f_core_array_push_back((S_Array*)面组, (uint8*)&face);
			}
		}
	}
	}
	
	S_Vec3Array vert;
	vert.ptr_userData = 顶点.data();
	vert.count = 顶点.size();

	S_Vec3Array normal;
	normal.ptr_userData = 法线.data();
	normal.count = 法线.size();
	f_surface_添加多边形顶点(poly, &vert, &normal);


	f_core_array_push_back((S_Array*)poly->m_元素组, (uint8*)&面组);

	return 面组;
}

void f_surface_投影纹理坐标(S_多边形* poly, int32 投影类型, S_多边形元素* 面元素, const Mat44f& mat) {
	auto* faceIndex_ptr = 面元素->ptr_userData;
	auto face_num = 面元素->count;

	auto* vert_ptr = poly->m_顶点.data();
	
	vec3 中心 = mat * vec3{};
	switch (投影类型) {
	case 0: {
		for (uint32 i = 0; i < face_num; ++i) {
			auto* face_ptr = faceIndex_ptr[i];
			uint32 vertIndexNum = face_ptr->vertIndex.size();
			uint32* vertIndex_ptr = face_ptr->vertIndex.data();

			auto& uvIndex = face_ptr->uvLoopIndex[0];

			uint32 UV开始偏移 = poly->m_UV.size();
			poly->m_UV索引.reserve(UV开始偏移 + vertIndexNum);

			for (uint32 j = 0; j < vertIndexNum; ++j) {
				poly->m_UV索引.push_back(poly->m_UV.size());

				vec3 v =  vert_ptr[vertIndex_ptr[j]] - 中心;
				poly->m_UV.push_back({ v.x, v.z });
				
			}
			uvIndex = { UV开始偏移, vertIndexNum };
		}
		break;
	}
	case 1: {
		break;
	}
	case 2: {
		break;
	}
	case 3: {
		for (uint32 i = 0; i < face_num; ++i) {
			auto* face_ptr = faceIndex_ptr[i];
			uint32 vertIndexNum = face_ptr->vertIndex.size();
			uint32* vertIndex_ptr = face_ptr->vertIndex.data();

			auto& uvIndex = face_ptr->uvLoopIndex[0];

			uint32 UV开始偏移 = poly->m_UV.size();
			poly->m_UV索引.reserve(UV开始偏移 + vertIndexNum);

			for (uint32 j = 0; j < vertIndexNum; ++j) {
				poly->m_UV索引.push_back(poly->m_UV.size());

				vec3 v =  vert_ptr[vertIndex_ptr[j]] - 中心;
				v = mat * v;
				//f_graph_两向量夹角弧度(v, 方向);
				vec2 uv = f_CylindricalProjectUV(v);
				
				poly->m_UV.push_back({ v.x, v.z });
				//uvIndex.push_back(poly->m_UV.size());
				//poly->m_UV.push_back(uv);
			}
			uvIndex = { UV开始偏移, vertIndexNum };
		}
		break;
	}
	case 4: {
		for (uint32 i = 0; i < face_num; ++i) {
			
			auto* face_ptr = faceIndex_ptr[i];
			uint32 vertIndexNum = face_ptr->vertIndex.size();
			uint32* vertIndex_ptr = face_ptr->vertIndex.data();

			auto& uvIndex = face_ptr->uvLoopIndex[0];

			uint32 UV开始偏移 = poly->m_UV.size();
			poly->m_UV索引.reserve(UV开始偏移 + vertIndexNum);

			for (uint32 j = 0; j < vertIndexNum; ++j) {
				poly->m_UV索引.push_back(poly->m_UV.size());

				vec3 v =  vert_ptr[vertIndex_ptr[j]] - 中心;
				v = mat * v;
				//f_graph_两向量夹角弧度(v, 方向);
				vec2 uv = f_equirectangularUV(v);
				//uvIndex.push_back(poly->m_UV.size());
				poly->m_UV.push_back(uv);
			}
			uvIndex = { UV开始偏移, vertIndexNum };
		}
		break;
	}
	}
}

void f_surface_多边形转网格(const S_多边形* 多边形, S_Mesh* 面网格, S_Mesh* 点网格, S_Mesh* 边网格, bool 计算平滑法线) {
	uint32 num = 多边形->m_顶点.size();
	std::vector<S_VNT1> 面顶点(num);
	std::vector<S_VC> 顶点边(num);
	auto* vert_ptr = 面顶点.data();


	for (uint32 i = 0; i < num; ++i) {
		顶点边[i].vert = vert_ptr[i].vert = 多边形->m_顶点[i];
		顶点边[i].color = f_PackData4X8({ 127,127,0,255 });

		vert_ptr[i].normal = {};
		vert_ptr[i].UV = {};
	}
	f_mesh_fill顶点数据(点网格, 顶点边);

	

	if (面网格) {
		auto uv = f_mesh_get多边形网格UV(面网格, 多边形);
		for (uint32 i = 0; i < num; ++i) {
			面顶点[i].UV = uv[i];
		}

		num = 多边形->m_面.size();
		if (num) {
			f_mesh_fill顶点数据(面网格, 面顶点);
			f_mesh_多边形三角化(面网格, 多边形);

			S_Bounding cube = f_mesh_计算包围盒(面网格);
			if (计算平滑法线) {
				f_surface_计算面平滑法线(面网格);
			}
		}
	}


	if (边网格) {
		f_surface_构建多边形边网格(边网格, 多边形->m_边_过时成员);
	}
}

void f_surface_创建自定义属性(S_多边形* 多边形, S_网格自定义属性* 类型) {
	std::set<std::u16string> key;
	switch (类型->m_分布方式) {
		case 0: {
			for (auto& e : 多边形->m_点自定义属性) {
				key.insert(e.first);
			}
			f_str_数组填充末尾(key, *类型->m_Name);
			

			if (多边形->m_点自定义属性.find(*类型->m_Name) == 多边形->m_点自定义属性.end()) {
				多边形->m_点自定义属性[*类型->m_Name] = f_core_array_new_type(多边形->m_顶点.size(), 类型->m_Type);
			}
			break;
		}
		case 1: {
			for (auto& e : 多边形->m_面自定义属性) {
				key.insert(e.first);
			}
			f_str_数组填充末尾(key, *类型->m_Name);

			if (多边形->m_面自定义属性.find(*类型->m_Name) == 多边形->m_面自定义属性.end()) {
				多边形->m_面自定义属性[*类型->m_Name] = f_core_array_new_type(多边形->m_面.size(), 类型->m_Type);
			}
			break;
		}
	}

	//nameProp->m_UI->m_部件-> = true;
}

void f_surface_设置自定义属性(S_多边形* 多边形, S_网格自定义属性* 类型, S_Array* a) {
	
	switch (类型->m_分布方式) {
		case 0: {
			if (多边形->m_点自定义属性.find(*类型->m_Name) != 多边形->m_点自定义属性.end()) {
				uint32 点数量 = 多边形->m_顶点.size();
				
				auto& e = 多边形->m_点自定义属性[*类型->m_Name];
				if (!e) return;
				
				bool 多例 = a->count >= 点数量;
				for (uint32 k = 0; k < 点数量; ++k) {
					f_core_array_元素复制(e, a, k, 多例 ? k : 0);
				}
			}
			break;
		}
		case 1: {
			if (多边形->m_面自定义属性.find(*类型->m_Name) != 多边形->m_面自定义属性.end()) {
				uint32 面数量 = 多边形->m_面.size();

				auto& e = 多边形->m_面自定义属性[*类型->m_Name];
				if (!e) return;

				auto* 面指针 = 多边形->m_面.data();

				bool 多例 = a->count >= 面数量;
				for (uint32 k = 0; k < 面数量; ++k) {
					f_core_array_元素复制(e, a, 面指针[k]->ID, 多例 ? k : 0);
					//f_core_array_元素复制(e, a, k, 多例 ? k : 0);
				}
			}
			break;
		}
	}
}

void f_surface_设置面自定义属性(S_多边形元素* 多边形元素, S_网格自定义属性* 类型, S_Array* a) {
	S_多边形* 多边形;
	if (多边形元素->count && 多边形元素->ptr_userData[0]) {
		多边形 = (S_多边形*)多边形元素->ptr_userData[0]->polygon;
	}
	else {
		return;
	}

	if((*类型->m_Name).empty()) return;

	switch (类型->m_分布方式) {
		case 0: {
			if (多边形->m_点自定义属性.find(*类型->m_Name) != 多边形->m_点自定义属性.end()) {
				
				auto& e = 多边形->m_点自定义属性[*类型->m_Name];
				if(!e) return;

				for (uint32 i = 0; i < 多边形元素->count; ++i) {
					auto* indexs = 多边形元素->ptr_userData[i]->vertIndex.data();
					uint32 faceVertNum = 多边形元素->ptr_userData[i]->vertIndex.size();

					bool 多例 = a->count >= faceVertNum;
					for (uint32 k = 0; k < faceVertNum; ++k) {
						f_core_array_元素复制(e, a, indexs[k], 多例 ? k : 0);
					}
				}
			}
			break;
		}
		case 1: {
			if (多边形->m_面自定义属性.find(*类型->m_Name) != 多边形->m_面自定义属性.end()) {
				auto& e = 多边形->m_面自定义属性[*类型->m_Name];
				
				//uint32 num = DEF_Min(a->count, 多边形元素->count);
				//bool 多例 = a->count <= 多边形元素->count;
				//for (uint32 i = 0; i < a->count; ++i) {
				//	f_core_array_元素复制(e, a, 多边形元素->ptr_userData[i]->ID, 多例 ? i : 0);
				//}

				bool 多例 = a->count >= 多边形元素->count;
				
				for (uint32 i = 0; i < 多边形元素->count; ++i) {
					f_core_array_元素复制(e, a, 多边形元素->ptr_userData[i]->ID, 多例 ? i : 0);
					//f_core_array_元素复制(e, a, i, 多例 ? i : 0);
				}
			}
			break;
		}
	}
}

void f_surface_设置元素自定义属性(S_多边形元素Array* 多边形元素组, S_网格自定义属性* 类型, S_Array* a) {
	if ((*类型->m_Name).empty()) return;

	bool 多例 = a->count >= 多边形元素组->count;
	for (uint32 i = 0; i < 多边形元素组->count; ++i) {
		S_多边形* 多边形;

		if(!多边形元素组->ptr_userData[i]) continue;

		S_多边形元素& 多边形元素 = *多边形元素组->ptr_userData[i];
		if (多边形元素.count && 多边形元素.ptr_userData[0]) {
			多边形 = (S_多边形*)多边形元素.ptr_userData[0]->polygon;
		}
		else {
			continue;
		}
		

		switch (类型->m_分布方式) {
			case 0: {
				if (多边形->m_点自定义属性.find(*类型->m_Name) != 多边形->m_点自定义属性.end()) {

					auto& e = 多边形->m_点自定义属性[*类型->m_Name];
					if (!e) continue;

					for (uint32 i = 0; i < 多边形元素.count; ++i) {
						auto* indexs = 多边形元素.ptr_userData[i]->vertIndex.data();
						uint32 faceVertNum = 多边形元素.ptr_userData[i]->vertIndex.size();

						for (uint32 k = 0; k < faceVertNum; ++k) {
							f_core_array_元素复制(e, a, indexs[k], 多例 ? i : 0);
						}
					}
				}
				break;
			}
			case 1: {
				if (多边形->m_面自定义属性.find(*类型->m_Name) != 多边形->m_面自定义属性.end()) {
					auto& e = 多边形->m_面自定义属性[*类型->m_Name];
					
					for (uint32 k = 0; k < 多边形元素.count; ++k) {
						f_core_array_元素复制(e, a, 多边形元素.ptr_userData[k]->ID, 多例 ? i : 0);
					}
				}
				break;
			}
		}
	}
}

S_GPU内存块 f_surface_填充自定义属性(S_Mesh* me, S_Array* a, int32 分布方式) {
	S_GPU内存块 块;
	switch (分布方式) {
		case 0: {
			switch (f_core_array_getType(a)) {

				case E_值类型::e_Type_F32_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_F32动态属性_点, 0);
					break;
				}
				case E_值类型::e_Type_I32_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_I32动态属性_点, 0);
					break;
				}
				case E_值类型::e_Type_UI32_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_UI32动态属性_点, 0);
					break;
				}
				case E_值类型::e_Type_Vec2_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_Vec2动态属性_点, 0);
					break;
				}
				case E_值类型::e_Type_Vec3_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_Vec3动态属性_点, 0);
					break;
				}
				case E_值类型::e_Type_Vec4_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_Vec4动态属性_点, 0);
					break;
				}
				case E_值类型::e_Type_iVec2_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_iVec2动态属性_点, 0);
					break;
				}
				case E_值类型::e_Type_iVec3_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_iVec3动态属性_点, 0);
					break;
				}
				case E_值类型::e_Type_iVec4_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_iVec4动态属性_点, 0);
					break;
				}
				default:
					break;
			}
			break;
		}
		case 1: {
			switch (f_core_array_getType(a)) {

				case E_值类型::e_Type_F32_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_F32动态属性_面, 0);
					break;
				}
				case E_值类型::e_Type_I32_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_I32动态属性_面, 0);
					break;
				}
				case E_值类型::e_Type_UI32_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_UI32动态属性_面, 0);
					break;
				}
				case E_值类型::e_Type_Vec2_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_Vec2动态属性_面, 0);
					break;
				}
				case E_值类型::e_Type_Vec3_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_Vec3动态属性_面, 0);
					break;
				}
				case E_值类型::e_Type_Vec4_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_Vec4动态属性_面, 0);
					break;
				}
				case E_值类型::e_Type_iVec2_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_iVec2动态属性_面, 0);
					break;
				}
				case E_值类型::e_Type_iVec3_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_iVec3动态属性_面, 0);
					break;
				}
				case E_值类型::e_Type_iVec4_1D: {
					块 = f_bm_alloc(f_buf_getGlobal().g_iVec4动态属性_面, 0);
					break;
				}
				default:
					break;
			}
			break;
		}
	}
	
	f_gbuf_fill(块, a->ptr_userData, 0, a->count);
	return 块;
}



void f_surface_多边形保存(FILE* f, const S_多边形* 多边形) {
	file_写入序列到文件(f, 多边形->m_顶点);
	file_写入序列到文件(f, 多边形->m_法线);
	file_写入序列到文件(f, 多边形->m_UV);
	file_写入序列到文件(f, 多边形->m_UV索引);
	

	uint32 num = 多边形->m_边_过时成员.size();
	fwrite(&num, sizeof(uint32), 1, f);
	auto edge_ptr = 多边形->m_边_过时成员.data();
	for (uint32 i = 0; i < num; ++i) {
		file_写入序列到文件(f, edge_ptr[i]->edge);
		edge_ptr[i]->edge;
	}

	num = 多边形->m_面.size();
	fwrite(&num, sizeof(uint32), 1, f);
	auto face_ptr = 多边形->m_面.data();
	for (uint32 i = 0; i < num; ++i) {
		file_写入序列到文件(f, face_ptr[i]->vertIndex);
		file_写入序列到文件(f, face_ptr[i]->uvLoopIndex);
		file_写入序列到文件(f, face_ptr[i]->edge);
		fwrite(&face_ptr[i]->材质槽, sizeof(uint32), 1, f);
	}
}

S_多边形* f_surface_多边形加载(FILE* f) {
	S_多边形* poly = f_surface_创建多边形();

	file_读取序列到文件(f, &(poly->m_顶点));
	file_读取序列到文件(f, &(poly->m_法线));
	file_读取序列到文件(f, &(poly->m_UV));
	file_读取序列到文件(f, &(poly->m_UV索引));


	uint32 num = 0;
	fread(&num, sizeof(uint32), 1, f);
	for (uint32 i = 0; i < num; ++i) {
		S_边* 边 = new S_边;
		file_读取序列到文件(f, &(边->edge));
		poly->m_边_过时成员.push_back(边);
	}

	fread(&num, sizeof(uint32), 1, f);
	for (uint32 i = 0; i < num; ++i) {
		S_面* 多边形面 = new S_面((S_结构指针)poly);
		
		file_读取序列到文件(f, &(多边形面->vertIndex));
		file_读取序列到文件(f, &(多边形面->uvLoopIndex));
		file_读取序列到文件(f, &(多边形面->edge));

		fread(&多边形面->材质槽, sizeof(uint32), 1, f);

		多边形面->ID = poly->m_面.size();
		poly->m_面.push_back(多边形面);
	}

	for (auto& e : poly->m_面自定义属性) {
		//f_core_array_resize(e.second, poly->m_面.size());
	}
	return poly;
}



void f_surface_多边形保存(S_UI8Array* 块, const S_多边形* 多边形, bool 压缩) {
	f_文件块_写序列数据块(块, 多边形->m_顶点, 压缩);
	f_文件块_写序列数据块(块, 多边形->m_法线, 压缩);
	f_文件块_写序列数据块(块, 多边形->m_UV, 压缩);
	f_文件块_写序列数据块(块, 多边形->m_UV索引, 压缩);


	uint32 num = 多边形->m_边_过时成员.size();
	f_文件块_写数据块(块, num);
	auto edge_ptr = 多边形->m_边_过时成员.data();
	for (uint32 i = 0; i < num; ++i) {
		f_文件块_写序列数据块(块, edge_ptr[i]->edge, 压缩);
	}

	num = 多边形->m_面.size();
	f_文件块_写数据块(块, num);
	auto face_ptr = 多边形->m_面.data();

	std::vector<uint32> 材质槽(num);
	std::vector<uint8> 面平直(num);
	for (uint32 i = 0; i < num; ++i) {
		f_文件块_写序列数据块(块, face_ptr[i]->vertIndex, 压缩);
		f_文件块_写序列数据块(块, face_ptr[i]->uvLoopIndex, 压缩);
		f_文件块_写序列数据块(块, face_ptr[i]->edge, 压缩);
		//f_文件块_写数据块(块, face_ptr[i]->材质槽);
		//f_文件块_写数据块(块, face_ptr[i]->面平直);
		材质槽[i] = face_ptr[i]->材质槽;
		面平直[i] = face_ptr[i]->面平直;
	}
	f_文件块_写序列数据块(块, 材质槽, 压缩);
	f_文件块_写序列数据块(块, 面平直, 压缩);
	材质槽.clear();
	面平直.clear();


	
	num = 多边形->m_元素组->count;
	f_文件块_写数据块(块, num);

	std::vector<uint32> 元素面数量(num);
	std::vector<uint32> 面ID;
	for (uint32 i = 0; i < num; ++i) {
		S_多边形元素* 元素 = 多边形->m_元素组->ptr_userData[i];
		uint32 面数量 = 元素->count;
		元素面数量[i] = 面数量;

		for (uint32 k = 0; k < 面数量; ++k) {
			面ID.push_back(元素->ptr_userData[k]->ID);
		}
	}
	f_文件块_写序列数据块(块, 元素面数量, 压缩);
	f_文件块_写序列数据块(块, 面ID, 压缩);
}

const uint8* f_surface_多边形加载(const uint8* 块, S_多边形* poly, bool 压缩) {
	
	块 = f_文件块_读序列数据块(块, poly->m_顶点, 压缩);
	块 = f_文件块_读序列数据块(块, poly->m_法线, 压缩);
	块 = f_文件块_读序列数据块(块, poly->m_UV, 压缩);
	块 = f_文件块_读序列数据块(块, poly->m_UV索引, 压缩);


	uint32 num = 0;
	块 = f_文件块_读数据块(块, num);
	
	for (uint32 i = 0; i < num; ++i) {
		S_边* 边 = new S_边;
		块 = f_文件块_读序列数据块(块, 边->edge, 压缩);
		poly->m_边_过时成员.push_back(边);
	}


	
	块 = f_文件块_读数据块(块, num);
	for (uint32 i = 0; i < num; ++i) {
		S_面* 多边形面 = new S_面((S_结构指针)poly);
		
		块 = f_文件块_读序列数据块(块, 多边形面->vertIndex, 压缩);
		块 = f_文件块_读序列数据块(块, 多边形面->uvLoopIndex, 压缩);
		块 = f_文件块_读序列数据块(块, 多边形面->edge, 压缩);

		多边形面->ID = poly->m_面.size();
		poly->m_面.push_back(多边形面);
	}
	std::vector<uint32> 材质槽;
	std::vector<uint8> 面平直;
	块 = f_文件块_读序列数据块(块, 材质槽, 压缩);
	块 = f_文件块_读序列数据块(块, 面平直, 压缩);
	for (uint32 i = 0; i < num; ++i) {
		poly->m_面[i]->材质槽 = 材质槽[i];
		poly->m_面[i]->面平直 = 面平直[i];
	}



	块 = f_文件块_读数据块(块, num);
	f_core_array_resize((S_Array*)poly->m_元素组, num);
	
	std::vector<uint32> 元素面数量;
	std::vector<uint32> 面ID;
	块 = f_文件块_读序列数据块(块, 元素面数量, 压缩);
	块 = f_文件块_读序列数据块(块, 面ID, 压缩);
	
	uint32 offset = 0;
//#pragma omp parallel for num_threads(DEF_Min(8, num))
	for (int32 i = 0; i < num; ++i) {
		uint32 面数量 = 元素面数量[i];
		S_多边形元素* 元素 = (S_多边形元素*)f_core_array_new(面数量, sizeof(S_面*), false, false);
	
		for (uint32 k = 0; k < 面数量; ++k) {
			uint32 id = 面ID[offset];
			元素->ptr_userData[k] = poly->m_面[id];
			++offset;
		}
		f_core_array_CleanUnusedMemory((S_Array*)元素);
		poly->m_元素组->ptr_userData[i] = 元素;
	}
	f_core_array_CleanUnusedMemory((S_Array*)poly->m_元素组);

	return 块;
}



void f_surface_网格保存(S_UI8Array* 块, const S_Mesh* me, bool 压缩) {
	const uint8* data = nullptr;
	switch (*me->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			data = (const uint8*)f_buf_VNT_ptr(*me->m_顶点);
			break;
		}
		case E_顶点组合标志::e_坐标_颜色: {
			data = (const uint8*)f_buf_VC_ptr(*me->m_顶点);
			break;
		}
		default:
			break;
	}
	
	f_文件块_写数据块(块, *me->m_顶点配置Flags);


	f_文件块_写数据块(块, me->m_顶点->m_Mem.m_数量);
	if(me->m_顶点->m_Mem.m_数量){
		f_文件块_写数据块(块, data, me->m_顶点->m_Mem.m_数量 * me->m_顶点->m_Buf->m_Offset);
	}

	f_文件块_写数据块(块, me->m_UV->m_Mem.m_数量);
	if (me->m_UV->m_Mem.m_数量) {
		f_文件块_写数据块(块, (const uint8*)f_buf_Vec2_ptr(*me->m_UV), me->m_UV->m_Mem.m_数量 * me->m_UV->m_Buf->m_Offset);
	}
	
	f_文件块_写数据块(块, me->m_UV索引->m_Mem.m_数量);
	if (me->m_UV索引->m_Mem.m_数量) {
		f_文件块_写数据块(块, (const uint8*)f_buf_uVec3_ptr(*me->m_UV索引), me->m_UV索引->m_Mem.m_数量 * me->m_UV索引->m_Buf->m_Offset);
	}

	f_文件块_写数据块(块, me->m_索引->m_Mem.m_数量);
	if (me->m_索引->m_Mem.m_数量) {
		f_文件块_写数据块(块, (uint8*)f_buf_UI32_ptr(*me->m_索引), me->m_索引->m_Mem.m_数量 * me->m_索引->m_Buf->m_Offset);
	}

	f_文件块_写数据块(块, me->m_面->m_Mem.m_数量);
	if (me->m_索引->m_Mem.m_数量) {
		f_文件块_写数据块(块, (uint8*)f_buf_面元素_ptr(*me->m_面), me->m_面->m_Mem.m_数量 * me->m_面->m_Buf->m_Offset);
	}

	f_文件块_写数据块(块, f_me_getBound(me));
	f_文件块_写数据块(块, f_me_get包围盒(me));
	
}

const uint8* f_surface_网格读取(const uint8* 块, S_Mesh* me, bool 压缩) {
	块 = f_文件块_读数据块(块 , *me->m_顶点配置Flags);


	uint32 顶点数量 = 0;
	块 = f_文件块_读数据块(块, 顶点数量);

	uint8* data = nullptr;
	switch (*me->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			std::vector<S_VNT1> data(顶点数量);
			块 = f_文件块_读数据块2((uint8*)data.data(), 块, 顶点数量 * sizeof(S_VNT1));

			f_mesh_fill顶点数据(me, data);
			break;
		}
		case E_顶点组合标志::e_坐标_颜色: {
			std::vector<S_VC> data(顶点数量);
			块 = f_文件块_读数据块2((uint8*)data.data(), 块, 顶点数量 * sizeof(S_VC));

			f_mesh_fill顶点数据(me, data);
			break;
		}
		default:
			break;
	}
	

	块 = f_文件块_读数据块(块, 顶点数量);
	f_bm_resize(*me->m_UV, 顶点数量);
	if (顶点数量) {
		me->m_UV->m_Buf->m_分配块内存锁.lock();
		块 = f_文件块_读数据块2((uint8*)f_buf_Vec2_ptr(*me->m_UV), 块, 顶点数量 * (me->m_UV->m_Buf->m_Offset));
		me->m_几何属性.uvLayerAndOffset.y = me->m_UV->m_Mem.m_偏移;
		me->m_UV->m_Buf->m_分配块内存锁.unlock();
	}
	
	块 = f_文件块_读数据块(块, 顶点数量);
	f_bm_resize(*me->m_UV索引, 顶点数量);
	if (顶点数量) {
		me->m_UV索引->m_Buf->m_分配块内存锁.lock();
		块 = f_文件块_读数据块2((uint8*)f_buf_uVec3_ptr(*me->m_UV索引), 块, 顶点数量 * (me->m_UV索引->m_Buf->m_Offset));
		me->m_UV索引->m_Buf->m_分配块内存锁.unlock();

		uint32 offset = me->m_UV索引->m_Mem.m_偏移;
		me->m_几何属性.uvIndexOffset012.x = 0;
		me->m_几何属性.uvIndexOffset012.y = 0;
		me->m_几何属性.uvIndexOffset012.z = 0;

		me->m_几何属性.uvLayerAndOffset.x = 1;
		//me->m_几何属性.uvLayerAndOffset.y = offset;
	}

	块 = f_文件块_读数据块(块, 顶点数量);
	f_bm_resize(*me->m_索引, 顶点数量);
	if (顶点数量) {
		me->m_索引->m_Buf->m_分配块内存锁.lock();
		块 = f_文件块_读数据块2((uint8*)f_buf_UI32_ptr(*me->m_索引), 块, 顶点数量 * (me->m_索引->m_Buf->m_Offset));
		me->m_索引->m_Buf->m_分配块内存锁.unlock();
	}

	块 = f_文件块_读数据块(块, 顶点数量);
	f_bm_resize(*me->m_面, 顶点数量);
	if (顶点数量) {
		me->m_面->m_Buf->m_分配块内存锁.lock();
		块 = f_文件块_读数据块2((uint8*)f_buf_面元素_ptr(*me->m_面), 块, 顶点数量 * (me->m_面->m_Buf->m_Offset));
		me->m_面->m_Buf->m_分配块内存锁.unlock();
	}


	块 = f_文件块_读数据块(块 , *me->m_Bound);
	块 = f_文件块_读数据块(块 , *me->m_包围盒);

	return 块;
}


S_多边形* f_surface_copy(const S_多边形* 多边形) {
	S_多边形* 新多边形 = f_surface_创建多边形();

	f_surface_copy(多边形, 新多边形);
	//新多边形->m_顶点 = 多边形->m_顶点;
	//新多边形->m_法线 = 多边形->m_法线;
	//新多边形->m_UV = 多边形->m_UV;
	//新多边形->m_UV索引 = 多边形->m_UV索引;
	//
	//
	//uint32 num = 多边形->m_边.size();
	//for (uint32 i = 0; i < num; ++i) {
	//	S_边* 边 = new S_边;
	//	边->edge = 多边形->m_边[i]->edge;
	//	新多边形->m_边.push_back(边);
	//}
	//
	//num = 多边形->m_面.size();
	//for (uint32 i = 0; i < num; ++i) {
	//	S_面* 多边形面 = new S_面;
	//	多边形面->polygon = (S_结构对象指针)多边形;
	//
	//	多边形面->vertIndex = 多边形->m_面[i]->vertIndex;
	//	多边形面->uvLoopIndex = 多边形->m_面[i]->uvLoopIndex;
	//	多边形面->edge = 多边形->m_面[i]->edge;
	//	多边形面->材质槽 = 多边形->m_面[i]->材质槽;
	//	新多边形->m_面.push_back(多边形面);
	//}
	return 新多边形;
}

void f_surface_copy(const S_多边形* 源多边形, S_多边形* 目标多边形) {
	目标多边形->m_顶点 = 源多边形->m_顶点;
	目标多边形->m_法线 = 源多边形->m_法线;
	目标多边形->m_UV = 源多边形->m_UV;
	目标多边形->m_UV索引 = 源多边形->m_UV索引;

	uint32 num = 源多边形->m_边_过时成员.size();
	for (uint32 i = 0; i < num; ++i) {
		S_边* 边 = new S_边;
		边->edge = 源多边形->m_边_过时成员[i]->edge;
		目标多边形->m_边_过时成员.push_back(边);
	}


	num = 源多边形->m_面.size();
	for (uint32 i = 0; i < num; ++i) {
		S_面* 多边形面 = new S_面((S_结构指针)目标多边形);
		//多边形面->polygon = (S_结构对象指针)目标多边形;

		多边形面->vertIndex = 源多边形->m_面[i]->vertIndex;
		多边形面->面法线 = 源多边形->m_面[i]->面法线;
		//多边形面->uvLoopIndex = 源多边形->m_面[i]->uvLoopIndex;
		多边形面->edge = 源多边形->m_面[i]->edge;
		多边形面->材质槽 = 源多边形->m_面[i]->材质槽;
		多边形面->ID = 目标多边形->m_面.size();

		目标多边形->m_面.push_back(多边形面);
	}


	//uint32 faceOffset = 0;
	//num = 源多边形->m_元素组->count;
	//
	//f_core_array_resize((S_Array*)目标多边形->m_元素组, num);
	//for (uint32 i = 0; i < num; ++i) {
	//	S_多边形元素* 元素 = 源多边形->m_元素组->ptr_userData[i];
	//
	//	uint32 面数量 = 元素->count;
	//	S_多边形元素* 新元素 = (S_多边形元素*)f_core_array_new(面数量, sizeof(S_面*));
	//	for (uint32 j = 0; j < 面数量; ++j) {
	//		新元素->ptr_userData[j] = 目标多边形->m_面[faceOffset];
	//		++faceOffset;
	//	}
	//
	//	目标多边形->m_元素组->ptr_userData[i] = 新元素;
	//}

	for (auto& e : 目标多边形->m_面自定义属性) {
		f_core_array_resize(e.second, 目标多边形->m_面.size());
	}
}


void f_mesh_清除重复索引(S_UI32Array* 网格索引) {

	int32 num = 网格索引->count;
	uint32* index = 网格索引->ptr_userData;

	for (int32 j = 0; j < num; ++j) {
		if (index[j] == -1) continue;

		for (int32 k = j + 1; k < num; ++k) {
			if (index[j] == index[k]) {
				index[k] = -1;
			}
		}
	}

	for (int32 j = 0; j < num; ) {
		if (网格索引->ptr_userData[j] == -1) {
			f_core_array_erase((S_Array*)网格索引, j);
			--num;
		}
		else {
			++j;
		}
	}
}

void f_mesh_清除网格元素中相同索引(S_UI32Array2D* 网格元素) {
	for (uint32 i = 0; i < 网格元素->count; ++i) {
		f_mesh_清除重复索引(网格元素->ptr_userData[i]);
	}
}









// 检查三个点是否形成凸顶点
bool isConvex(const vec2& p, const vec2& q, const vec2& r) {
	double crossProduct = (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x);
	return crossProduct > 0;
}

// 检查一个点是否在三角形内部
bool isInsideTriangle(const vec2& point, const vec2& p, const vec2& q, const vec2& r) {
	double ax = q.x - p.x;
	double ay = q.y - p.y;
	double bx = r.x - p.x;
	double by = r.y - p.y;
	double cx = point.x - p.x;
	double cy = point.y - p.y;

	double det = ax * by - ay * bx;
	if (det == 0) return false;

	double u = (cx * by - cy * bx) / det;
	double v = (ax * cy - ay * cx) / det;

	return (u > -1e-9) && (v > -1e-9) && (u + v < 1 + 1e-9);
}


// 检查一个顶点是否是耳朵
bool isEar(const std::vector<vec2>& points, uint32_t p, uint32_t q, uint32_t r, const std::vector<uint32_t>& indices) {
	// 检查是否是凸顶点
	if (isConvex(points[p], points[q], points[r])) {
		// 检查三角形内部是否包含其他顶点
		for (uint32_t index : indices) {
			if (index != p && index != q && index != r) {
				if (isInsideTriangle(points[index], points[p], points[q], points[r])) {
					return false;
				}
			}
		}
		return true;
	}
	return false;
}






// 四叉树节点类
class f_polygon_QuadTreeNode {
public:
	float minX, maxX, minY, maxY;
	std::vector<uint32> pointIndices;
	std::vector<f_polygon_QuadTreeNode*> children;

	f_polygon_QuadTreeNode(float _minX, float _maxX, float _minY, float _maxY)
		: minX(_minX), maxX(_maxX), minY(_minY), maxY(_maxY) {}

	~f_polygon_QuadTreeNode() {
		for (auto child : children) {
			delete child;
		}
	}

	void insert(const std::vector<vec3>& vertices, uint32 index) {
		if (pointIndices.size() < 10) {
			pointIndices.push_back(index);
			return;
		}

		if (children.empty()) {
			float midX = (minX + maxX) / 2;
			float midY = (minY + maxY) / 2;
			children.resize(4);
			children[0] = new f_polygon_QuadTreeNode(minX, midX, minY, midY);
			children[1] = new f_polygon_QuadTreeNode(midX, maxX, minY, midY);
			children[2] = new f_polygon_QuadTreeNode(minX, midX, midY, maxY);
			children[3] = new f_polygon_QuadTreeNode(midX, maxX, midY, maxY);
		}

		vec3 point = vertices[index];
		for (auto child : children) {
			if (point.x >= child->minX && point.x < child->maxX &&
				point.y >= child->minY && point.y < child->maxY) {
				child->insert(vertices, index);
				return;
			}
		}
	}

	void query(const std::vector<vec3>& vertices, const vec3& a, const vec3& b, const vec3& c, std::vector<uint32>& result) {
		for (auto index : pointIndices) {
			if (f_polygon_isPointInTriangle(vertices[index], a, b, c)) {
				result.push_back(index);
			}
		}

		for (auto child : children) {
			if (child) {
				child->query(vertices, a, b, c, result);
			}
		}
	}
};




// 环信息（包含原始顶点索引和方向）
struct Loop {
	std::vector<uint32> indices; // 保持原始顶点顺序
	bool isOuter; // true=外边界（顺时针），false=孔（逆时针）
};

// 计算环面积（带符号）
float loopSignedArea(const std::vector<vec2>& v, const std::vector<uint32>& idx) {
	float area = 0.0f;
	for(size_t i=0; i<idx.size(); ++i) {
		const vec2& p1 = v[idx[i]];
		const vec2& p2 = v[idx[(i+1)%idx.size()]];
		area += p1.x * p2.y - p2.x * p1.y;
	}
	return area * 0.5f;
}

// 分解环（保持原始顶点顺序和方向）
std::vector<Loop> parseLoops(const std::vector<vec2>& vertices, 
							 const std::vector<std::vector<uint32>>& edgeIndices) {
	std::vector<Loop> loops;
	for(const auto& idx : edgeIndices) {
		Loop loop;
		loop.indices = idx;
		loop.isOuter = (loopSignedArea(vertices, idx) < 0); // 外边界应为负面积
		loops.push_back(loop);
	}
	return loops;
}

// 计算三角形面积（基于原始顶点）
float triangleArea(const std::vector<vec2>& v, uint32 a, uint32 b, uint32 c) {
	return std::abs(cross(v[a], v[b], v[c])) * 0.5f;
}

// 耳切法（仅使用原始顶点）
std::vector<uint32> earclip(const std::vector<vec2>& v, std::vector<uint32>& idx,
							float targetArea, float tolerance=0.2f) {
	std::vector<uint32> tris;
	std::vector<bool> isEar(idx.size(), true);

	for(size_t n=idx.size(); n>2; ) {
		bool found = false;
		for(size_t i=0; i<idx.size(); ++i) {
			if(!isEar[i]) continue;

			size_t prev = (i-1+idx.size())%idx.size();
			size_t next = (i+1)%idx.size();

			// 检查凹角（外边界顺时针，孔逆时针）
			float c = cross(v[idx[prev]], v[idx[i]], v[idx[next]]);
			bool isConvex = (c > 1e-6f) == idx.empty(); // 外边界凸角判断相反

			if(!isConvex) continue;

			// 检查耳内无其他顶点
			bool isClear = true;
			for(size_t k=0; k<idx.size(); ++k) {
				if(k == prev || k == i || k == next) continue;
				if(cross(v[idx[prev]], v[idx[i]], v[idx[k]]) >= 0 &&
				   cross(v[idx[i]], v[idx[next]], v[idx[k]]) >= 0 &&
				   cross(v[idx[next]], v[idx[prev]], v[idx[k]]) >= 0) {
					isClear = false;
					break;
				}
			}

			if(isClear) {
				// 检查面积均匀性
				float area = triangleArea(v, idx[prev], idx[i], idx[next]);
				if(area > targetArea * (1 - tolerance) &&
				   area < targetArea * (1 + tolerance)) {
					tris.push_back(idx[prev]);
					tris.push_back(idx[i]);
					tris.push_back(idx[next]);

					// 移除当前顶点
					isEar[i] = false;
					idx.erase(idx.begin() + i);
					isEar.erase(isEar.begin() + i);
					n--;
					found = true;
					break;
				}
			}
		}
		if(!found) break; // 无法继续剖分（非流形结构）
	}
	return tris;
}



static uvec2 f_耳切内最近点(const vec2 p[3], 
							uint32 当前路径ID, 
							uvec3 排除点索引, 
							const vec2* vertices, 
							const std::vector<uint32>& index, 
							const std::vector<uvec2>& edgeIndices, 
							uint8* 外圈, 
							bool& 前) {
	uint32 路径数量 = index.size();

	float32 离线最近点 = 10000000000;
	uvec2 离线最近点索引 = {-1,-1};
	const double epsilon = 1e-8;

	float32 qA = cross(p[0], p[1], p[2]) + epsilon;
	float32 qB = cross(p[1], p[2], p[0]) + epsilon;
	float32 qC = cross(p[2], p[0], p[1]) + epsilon;

	for (uint32 路径ID = 0; 路径ID < 路径数量; ++路径ID) {
		const auto i = index[路径ID];
		const auto e = edgeIndices[i];
		
		if (当前路径ID == e.x) {
			if(排除点索引.x == i || 排除点索引.y == i || 排除点索引.z == i) continue;
		}
		else {
			if(外圈[e.x]) continue;
		}

		vec2 cp = vertices[i];

		float32 xA = cross(p[0], p[1], cp);
		float32 xB = cross(p[1], p[2], cp);
		float32 xC = cross(p[2], p[0], cp);


		bool has_pos = (xA > qA) && (xB > qB) && (xC > qC);
		has_pos &= (xA <= epsilon && xB <= epsilon && xC <= epsilon);

		if (has_pos) {
			float32 d1 = length(cp - p[1]);

			if(d1 < 离线最近点) {
				离线最近点 = d1;
				离线最近点索引 = e;
			}
		}
		
	}
	return 离线最近点索引;
}


uvec2 f_耳切内最近点(const vec2 p[3], uint32 当前路径ID, uvec3 排除点索引, const vec2* vertices, std::vector<std::vector<uint32>> edgeIndices, uint8* 外圈, bool& 前) {
	uint32 路径数量 = edgeIndices.size();

	float32 离线最近点 = 10000000000;
	uvec2 离线最近点索引 = {-1,-1};
	const double epsilon = 1e-8;

	float32 qA = cross(p[0], p[1], p[2]) + epsilon;
	float32 qB = cross(p[1], p[2], p[0]) + epsilon;
	float32 qC = cross(p[2], p[0], p[1]) + epsilon;

	for (uint32 路径ID = 0; 路径ID < 路径数量; ++路径ID) {
		const auto& e = edgeIndices[路径ID];
		uint32 vNum = e.size();
		
		for (uint32 i = 0; i < vNum; ++i) {
			if (当前路径ID == 路径ID) {
				if(排除点索引.x == i || 排除点索引.y == i || 排除点索引.z == i) continue;
			}
			else {
				if(外圈[路径ID]) continue;
			}
			
			uint32 id = e[i];
			vec2 cp = vertices[id];

			float32 xA = cross(p[0], p[1], cp);
			float32 xB = cross(p[1], p[2], cp);
			float32 xC = cross(p[2], p[0], cp);

			bool has_pos = (xA > qA) && (xB > qB) && (xC > qC);
			has_pos &= (xA <= epsilon && xB <= epsilon && xC <= epsilon);

			if (has_pos) {
				float32 d1 = length(cp - p[1]);

				if(d1 < 离线最近点) {
					离线最近点 = d1;
					离线最近点索引 = {路径ID, i};
				}
			}
		}
	}
	return 离线最近点索引;
}

uvec3 f_最小凸角(const vec2* vertices, const uint32* edgeIndices, int32 点数量) {
	float32 最小角度 = 10;
	uvec3 最小角度ID = {};

	int32 num = 点数量 - 2;

	uint32 点ID = 0;
	for (; 点ID < num; ++点ID) {
		vec2 p1 = vertices[edgeIndices[点ID]];
		vec2 p2 = vertices[edgeIndices[点ID+1]];
		vec2 p3 = vertices[edgeIndices[点ID+2]];

		p3 = normalize(p3 - p2);
		p2 = normalize(p2 - p1);
		float32 q = cross1D(p2, p3);
		//float32 q = (p3.x - p2.x) * (p3.y + p2.y);
		if (q >= 0) {
			q = dot(p2, p3) + 1;

			if (q < 最小角度) {
				最小角度 = q;
				最小角度ID = {点ID, 点ID+1, 点ID+2};
			}
		}
	}

	for (int32 i = 0; i < 2; ++i) {
		uvec3 ID = {(num + i + 0) % 点数量, (num + i + 1) % 点数量, (num + i + 2) % 点数量};
		
		vec2 p1 = vertices[edgeIndices[ID.x]];
		vec2 p2 = vertices[edgeIndices[ID.y]];
		vec2 p3 = vertices[edgeIndices[ID.z]];

		p3 = normalize(p3 - p2);
		p2 = normalize(p2 - p1);
		float32 q = cross1D(p2, p3);
		//float32 q = (p3.x - p2.x) * (p3.y + p2.y);
		if (q >= 0) {
			q = dot(p2, p3) + 1;

			if (q < 最小角度) {
				最小角度 = q;
				最小角度ID = ID;
			}
		}
	}
	return 最小角度ID;
}

static std::vector<uint32> f_环分离(std::vector<uint32>& 外环, int32 凸点, int32 分割点) {
	std::vector<uint32> 新环;

	if (凸点 > 分割点) {
		//if (凸点 - 分割点 > 1) {
			新环.insert(新环.begin(), 外环.begin() + 分割点, 外环.begin() + 凸点 + 1);
		//}
		外环.erase(外环.begin() + 分割点 + 1, 外环.begin() + 凸点);
	}
	else {
		//if (分割点 - 凸点 > 1) {
			新环.insert(新环.begin(), 外环.begin() + 凸点, 外环.begin() + 分割点 + 1);
		//}
		外环.erase(外环.begin() + 凸点 + 1, 外环.begin() + 分割点);
	}

	return 新环;
}

static void f_内环加入外环(std::vector<uint32>& 外环, const std::vector<uint32>& 内环, int32 外环开始点, int32 内环开始点) {
	int32 num = 内环.size();

	std::vector<uint32> 新内环(num + 1);
	for (int32 i = 0; i <= num; ++i) {
		int32 id = (i+内环开始点) % num;
		新内环[i] = 内环[id];
	}

	外环.insert(外环.begin() + 外环开始点, *(外环.begin() + 外环开始点));
	外环.insert(外环.begin() + 外环开始点 + 1, 新内环.begin(), 新内环.end());
}

// 对所有环进行三角剖分
std::vector<uint32> f_polygon_triangulate(const std::vector<vec2>& vertices, std::vector<std::vector<uint32>> edgeIndices) {
	if(vertices.empty() || edgeIndices.empty())  return {};
	//return {};

	std::vector<uint32> triangles;

	uint32 坐标数量 = vertices.size();
	uint32 圈数量 = edgeIndices.size();

	//S_球形四叉树<uint32> qt({0.5,0.5}, 1.0);
	std::vector<uvec2> 顶点所属路径(坐标数量);

	//f_shapeTree_添加数据(qt, uint32(0), {0.75f,0.75f}, 0.05);
	//std::vector<uint32> 周围顶点索引;
	//f_shapeTree_查找数据(qt, {0.975f,0.975f}, 0.1, 周围顶点索引);
	

	std::vector<uint8> 是否顺时针;
	for (uint32 圈ID = 0; 圈ID < 圈数量; ++圈ID) {
		auto& 圈 = edgeIndices[圈ID];
		uint32 点数量 = 圈.size();
		float32 area = 0;

		for (uint32 i = 0; i < 点数量; ++i) {
			uvec2 edge = {圈[i], 圈[(i + 1) % 点数量]};
			vec2 p0 = vertices[edge.x];
			vec2 p1 = vertices[edge.y];

			area += cross1D(p0, p1);

			//f_shapeTree_添加数据(qt, edge.x, p0, 0.1);
			顶点所属路径[edge.x] = {圈ID, i};
		}

		area *= 0.5;
		if (area >= 0) {
			是否顺时针.push_back(true);
		}
		else {
			是否顺时针.push_back(false);
		}
	}

	

	for (uint32 i = 0; i < 圈数量; ++i) {
		if (是否顺时针[i]) {
			
			for (auto it = edgeIndices[i].begin(); it < edgeIndices[i].end(); ) {
				auto& 路径 = edgeIndices[i];

				uint32 路径点数量 = 路径.size();
				if (路径点数量 >= 3) {
					const uvec3 最小角度ID = f_最小凸角(vertices.data(), edgeIndices[i].data(), 路径点数量);

					vec2 p[3] = { vertices[路径[最小角度ID.x]], vertices[路径[最小角度ID.y]], vertices[路径[最小角度ID.z]] };
					
					bool 前边 = false;
					uvec2 最近点ID = f_耳切内最近点(p, i, 最小角度ID, vertices.data(), edgeIndices, 是否顺时针.data(), 前边);
					
					

					
					if (最近点ID.x != -1) {
						if (最近点ID.x == i) {
							
 							std::vector<uint32> 新路径 = f_环分离(路径, 最小角度ID.y, 最近点ID.y);
							if (新路径.size()) {
								for (auto& e : 新路径) {
									顶点所属路径[e].y = 圈数量;
								}
								edgeIndices.emplace_back(std::move(新路径));
								是否顺时针.emplace_back(true);
								++圈数量;
							}
						}
						else {
							auto& 当前圈 = edgeIndices[最近点ID.x];
							for (auto& e : 当前圈) {
								顶点所属路径[e].y = i;
							}
							//内圈路径添加到当前路径
							f_内环加入外环(路径, 当前圈, 最小角度ID.y, 最近点ID.y);
							当前圈.clear();
						}
						it = edgeIndices[i].begin();
						continue;
					}
					else {
						uvec3 三角形索引 = 最小角度ID;

						三角形索引.x = 路径[最小角度ID.x];
						三角形索引.y = 路径[最小角度ID.y];
						三角形索引.z = 路径[最小角度ID.z];

						路径.erase(路径.begin() + 最小角度ID.y);

						triangles.emplace_back(三角形索引.x);
						triangles.emplace_back(三角形索引.y);
						triangles.emplace_back(三角形索引.z);
					}

					if(edgeIndices[i].empty()) break;
					it = edgeIndices[i].begin();

				}
				else if(路径点数量 == 3) {
					//triangles.emplace_back(edgeIndices[i][0]);
					//triangles.emplace_back(edgeIndices[i][1]);
					//triangles.emplace_back(edgeIndices[i][2]);
					edgeIndices[i].clear();
					break;
				}
				else {
					break;
				}
					
			}
			
		}
	}
	
	return triangles;
}






uint8 f_最小凸角(const vec2* point, std::list<S_2D路径顶点索引>& paths, S_2D三角形迭代器& 最小角度三角形) {

	int32 num = paths.size();
	if(num <= 3) {
		最小角度三角形.ix = paths.begin();
		最小角度三角形.iy = std::next(最小角度三角形.ix);
		最小角度三角形.iz = std::next(最小角度三角形.iy);
		return 2;
	}
	--num;

	float32 最小角度 = 10;
	uint8 存在 = 0;

	auto a = --paths.end();
	auto b = paths.begin();
	auto c = ++paths.begin();
	for (auto i = 0; i <= num; ) {

		vec2 p1 = point[a->p];
		vec2 p2 = point[b->p];
		vec2 p3 = point[c->p];

		p3 = normalize(p3 - p2);
		p2 = normalize(p2 - p1);
		//float32 q = cross1D(p2, p3);
		float32 q = cross(p2, p3);

		if (q <= 0) {
			q = dot(p2, p3) + 1;

			if (q < 最小角度) {
				最小角度 = q;
				最小角度三角形 = {a,b,c};
				存在 = 1;
			}
		}

		++i;
		if (i == 1) {
			a = paths.begin();
			++c;
		}
		else if (i) {
			++a;

			if (i >= num) {
				c = paths.begin();
			}
			else {
				c++;
			}
		}
		else {
			a = b;
			c++;
		}
		b++;
	}

	return 存在;
}


S_2D路径顶点索引 f_耳切内最近点(const vec2 p[3], 
					 const uvec3 当前顶点ID, 
					 uint32 当前路径ID, 
					 const std::vector<std::set<S_2D路径顶点索引*>*>& paths, 
					 vec2* point, 
					 uint8* 外圈,
					 uint32& 树层
) {
	S_2D路径顶点索引 最近点迭代器{{}, -1, uint64(0)};
	uint32 路径数量 = paths.size();
	
	
	float32 离线最近点 = 10000000000;
	bool 找到 = false;
	const double epsilon = 1e-8;
	
	float32 qA = cross(p[0], p[1], p[2]) + epsilon;
	float32 qB = cross(p[1], p[2], p[0]) + epsilon;
	float32 qC = cross(p[2], p[0], p[1]) + epsilon;
	
	for (uint32 路径ID = 0; 路径ID < 路径数量; ++路径ID) {
		auto e = *(paths[路径ID]);
		uint32 vNum = e.size();
	
		for (auto it = e.begin(); it != e.end(); ++it) {
			uint32 index = (*it)->p;
			uint32 路径层 = (*it)->层;
			if (当前路径ID == 路径层) {
				if(当前顶点ID.x == index || 当前顶点ID.y == index || 当前顶点ID.y == index) continue;
			}
			else {
				if(外圈[路径层]) continue;
			}
	
			vec2 cp = point[index];
			float32 xA = cross(p[0], p[1], cp);
			float32 xB = cross(p[1], p[2], cp);
			float32 xC = cross(p[2], p[0], cp);
	
			bool has_pos = (xA > qA) && (xB > qB) && (xC > qC);
			has_pos &= (xA <= epsilon && xB <= epsilon && xC <= epsilon);
	
			if (has_pos) {
				float32 d1 = length(cp - p[1]);
	
				if(d1 < 离线最近点) {
					离线最近点 = d1;
					最近点迭代器 = **it;
					树层 = 路径ID;
					找到 = true;
				}
			}
		}
	}
	return 最近点迭代器;
}

static std::list<S_2D路径顶点索引> f_环分离2(std::list<S_2D路径顶点索引>& 外环, t_2D顶点索引迭代器& 凸点, t_2D顶点索引迭代器& 分割点) {
	std::list<S_2D路径顶点索引> 新环;

	auto it = std::find(凸点, 外环.end(), *分割点);
	auto b_cp = *凸点;
	auto e_cp = *分割点;

	b_cp.idName = std::hash<uint64>()(b_cp.p * (b_cp.层+1) | (uint64) & 凸点);
	e_cp.idName = std::hash<uint64>()(e_cp.p * (e_cp.层+1) | (uint64) & 凸点);
	
	if (it != 外环.end()) {
		新环.push_front(std::move(b_cp));
		新环.splice(新环.end(), 外环, std::next(凸点), 分割点);
		新环.push_back(std::move(e_cp));
	}
	else {
		新环.push_front(std::move(e_cp));
		新环.splice(新环.end(), 外环, std::next(分割点), 凸点);
		新环.push_back(std::move(b_cp));
		
	}

	return 新环;
}

static void f_内环加入外环(std::list<S_2D路径顶点索引>& 外环, 
							std::list<S_2D路径顶点索引>& 内环, 
							t_2D顶点索引迭代器& 外环开始点, 
							t_2D顶点索引迭代器& 内环开始点,
							S_2D路径顶点索引* 新元素[2]) {

	uint32 num = 内环.size();

	auto 外环分界重复元素 = *外环开始点;
	外环分界重复元素.f_setHash((uint64) & 外环分界重复元素);
	t_2D顶点索引迭代器 it_外环分界重复元素 = 外环.insert(std::next(外环开始点), 外环分界重复元素);
	
	auto 内环分界重复元素 = *内环开始点;
	内环分界重复元素.f_setHash((uint64) & 内环分界重复元素);
	t_2D顶点索引迭代器 it_内环分界重复元素 = 内环.insert(std::next(内环开始点), 内环分界重复元素);

	外环.splice(it_外环分界重复元素, 内环, it_内环分界重复元素, 内环.end());
	外环.splice(it_外环分界重复元素, 内环, 内环.begin(), 内环.end());
	新元素[0] = &(*it_外环分界重复元素);
	新元素[1] = &(*it_内环分界重复元素);
}

static std::set<S_2D路径顶点索引*> 重复元素;
void f_text_四叉树值遍历(S_球形四叉树<S_2D路径顶点索引*>& tree) {
	for (uint32 i = 0; i < 4; ++i) {
		if (tree.m_子节点[i]) {
			for (auto& e : tree.m_子节点[i]->m_数据) {
				e->p;
				if (e->层 > 1024 || e->p > 10240000) {
					std::cout<<"error\n";
				}
				if (重复元素.find(e) != 重复元素.end()) {
					std::cout<<"error 重复元素\n";
				}
				else {
					重复元素.insert(e);
				}
			}
			f_text_四叉树值遍历(*tree.m_子节点[i]);
		}
	}
}


std::vector<uint32_t> f_polygon_从链表构建三角形(S_2D路径层 paths, float32 包围大小) {
	uint32 路径数量 = paths.index.size();
	std::vector<uint32> triangles;

	S_球形四叉树<S_2D路径顶点索引*> qt({0.5,0.5}, 包围大小);
	std::list<uint32>::iterator p;

	auto& vertices = paths.point;
	std::vector<uint8> 是否顺时针;
	if (路径数量 == 1 && 0) {
		是否顺时针.emplace_back(1);
	}
	else {
		bool 以有方向 = paths.inOut.size();

		for (uint32 圈ID = 0; 圈ID < 路径数量; ++圈ID) {

			if (以有方向) {
				if (paths.inOut[圈ID] == E_PathType2D::OuterRing) {
					是否顺时针.push_back(true);
				}
				else {
					是否顺时针.push_back(false);
				}
			}
			else {
				auto& 圈 = *std::next(paths.index.begin(), 圈ID);
				uint32 点数量 = 圈.size();
				float32 area = 0;

				auto it = 圈.begin();
				for (uint32 i = 1; i <= 点数量; ++i) {
					f_shapeTree_添加数据(qt, &(*it), vertices[it->p], 0.1);

					auto a = it;
					auto b = ++it;
					if (i >= 点数量) {
						b = 圈.begin();
					}
					area += cross1D(vertices[a->p], vertices[b->p]);
				}

				if (area >= 0) {
					是否顺时针.push_back(true);
				}
				else {
					是否顺时针.push_back(false);
				}
			}
		}
	}
	

	for (uint32 i = 0; i < 路径数量; ++i) {
		if (是否顺时针[i]) {
			
			auto& 路径 = *std::next(paths.index.begin(), i);
			for (auto it = 路径.begin(); it != 路径.end(); ) {
				
				uint32 路径点数量 = 路径.size();
				if (路径点数量 >= 3) {
					S_2D三角形迭代器 三角形迭代器;
					std::vector<std::set<S_2D路径顶点索引*>*> 周围顶点索引;

					uint8 分解 = f_最小凸角(&vertices[0], 路径, 三角形迭代器);
					
					
					if (分解 == 1) {
						uvec3 三角形索引 = 三角形迭代器;
						vec2 p[3] = { vertices[三角形索引.x], vertices[三角形索引.y], vertices[三角形索引.z] };

						vec2 center = f_graph_三角形外切圆中心(p[0], p[1], p[2]);
						float32 r = f_graph_三角形外切圆半径(p[0], p[1], p[2]);
						f_shapeTree_查找数据(qt, center, r, 周围顶点索引);

						//f_text_四叉树值遍历(qt);
						//重复元素.clear();

						uint32 层 = 0; 
						S_2D路径顶点索引 最近点顶点索引 = f_耳切内最近点(p, 三角形索引, i, 周围顶点索引, vertices.data(), 是否顺时针.data(), 层);
						
						if (最近点顶点索引.层 != -1) {
							
							if (最近点顶点索引.层 == i) {
								auto 最近点顶点迭代器 = std::find(路径.begin(), 路径.end(), 最近点顶点索引);
					
								std::list<S_2D路径顶点索引> 新路径 = f_环分离2(路径, 三角形迭代器.iy, 最近点顶点迭代器);
								if (新路径.size()) {
									for(auto& e : 新路径) e.层 = 路径数量;
									f_shapeTree_添加数据(qt, &(新路径.front()), vertices[新路径.front().p], 0.1);
									f_shapeTree_添加数据(qt, &(新路径.back()), vertices[新路径.back().p], 0.1);
									
									paths.index.emplace_back(std::move(新路径));
									是否顺时针.emplace_back(true);
									++路径数量;
								}
								//f_text_四叉树值遍历(qt);
								//重复元素.clear();
							}
							else {
								auto& 附加圈 = *std::next(paths.index.begin(), 最近点顶点索引.层);
								auto 最近点顶点迭代器 = std::find(附加圈.begin(), 附加圈.end(), 最近点顶点索引);
								for(auto& e : 附加圈) e.层 = i;
								//内圈路径添加到当前路径
								S_2D路径顶点索引* 新元素[2];
								f_内环加入外环(路径, 附加圈, 三角形迭代器.iy, 最近点顶点迭代器, 新元素);
					
								f_shapeTree_添加数据(qt, 新元素[0], vertices[新元素[0]->p], 0.1);
								f_shapeTree_添加数据(qt, 新元素[1], vertices[新元素[1]->p], 0.1);
								//f_text_四叉树值遍历(qt);
								//重复元素.clear();
							}
						}
						else {
							goto To_添加三角形;
						}
						
					}
					else if(分解 == 2) {
						To_添加三角形:
						uvec3 三角形索引 = 三角形迭代器;
						
						bool 成功清除 = false;
						for (uint32 i = 0; i < 4; ++i) {
							for (auto& e : 周围顶点索引) {
								if (e->erase(&(*三角形迭代器.iy))) {
									成功清除 = true;
									break;
								}
							}

							if (成功清除) {
								break;
							}
							else {
								周围顶点索引.clear();
								f_shapeTree_查找数据(qt, vertices[三角形索引.y], 0.01, 周围顶点索引);
								//f_text_四叉树值遍历(qt);
								//重复元素.clear();
							}
						}
						//f_text_四叉树值遍历(qt);
						//重复元素.clear();

						triangles.emplace_back(三角形迭代器.ix->p);
						triangles.emplace_back(三角形迭代器.iy->p);
						triangles.emplace_back(三角形迭代器.iz->p);

						路径.erase(三角形迭代器.iy);

						//f_text_四叉树值遍历(qt);
						//重复元素.clear();
					}
					else {
						++it;
						continue;
					}

					auto& 当前路径 = *std::next(paths.index.begin(), i);
					if(当前路径.empty()) break;
					it = 当前路径.begin();
				}
				else {
					break;
				}
			}
		}
	}
	return triangles;
}

void f_polygon_剔除重复顶点索引(const std::vector<vec2>& vertices, std::vector<std::vector<uint32>>& edgeIndices) {
	for (auto& e : edgeIndices) {
		if(e.empty()) continue;

		vec2 上一个坐标 = vertices[e.front()];
		for (auto it = e.begin() + 1; it != e.end(); ) {
			vec2 tv = vertices[*it];
			if (上一个坐标 == tv) {
				it = e.erase(it);
			}
			else {
				上一个坐标 = tv;
				++it;
			}
		}

		if (vertices[e.front()] == vertices[e.back()]) {
			e.pop_back();
		}
	}
}

S_2D路径层 f_polygon_构建2D路径(const std::vector<vec2>& vertices, const std::vector<std::vector<uint32>>& edgeIndices) {
	S_2D路径层 paths;
	uint32 index = 0;
	uint32 layer = 0;

	for (auto& e : edgeIndices) {
		if(e.empty()) continue;
		std::list<S_2D路径顶点索引> path;

		vec2 上一个坐标 = vertices[e.front()];
		paths.point.push_back(上一个坐标);
		path.push_back({index, layer, std::hash<uint64>()(index * (layer+1) | index) });
		++index;

		for (auto it = e.begin() + 1; it != e.end(); ++it) {
			vec2 tv = vertices[*it];
			paths.point.push_back(tv);

			if (上一个坐标 == tv) {
				//goto To_Test;
			}
			else {
				//To_Test:
				path.push_back({index, layer, std::hash<uint64>()(index * (layer+1) | index) });
				上一个坐标 = tv;
			}
			++index;
		}

		if (vertices[e.front()] == vertices[e.back()]) {
			path.pop_back();
		}

		paths.index.emplace_back(std::move(path));
		++layer;
	}
	return paths;
}





S_2D线段路径 f_polygon_构建2D线段路径(const std::vector<vec2>& vertices, const std::vector<std::vector<uint32>>& edgeIndices) {
	S_2D线段路径 paths;
	uint32 index = 0;

	for (auto& e : edgeIndices) {
		int32 num = e.size();
		if(num < 2) continue;

		const uint32* 路径索引 = e.data();
		std::vector<uvec2> path;

		vec2 上一个坐标 = vertices[路径索引[0]];
		paths.point.push_back(上一个坐标);

		for (uint32 i = 1 ; i < num; ++i) {
			vec2 tv = vertices[路径索引[i]];

			if (上一个坐标 != tv) {
				paths.point.push_back(tv);
				path.push_back({ index,  ++index });
			}
			上一个坐标 = tv;
			
		}
		if (上一个坐标 != vertices[ 路径索引[0] ]) {
			path.push_back({uint32(index), path.front().x});
		}

		paths.index.emplace_back(std::move(path));

	}
	return paths;
}

S_2D三角形 f_polygon_扫描构建三角形(const S_2D线段路径& 线段) {
	S_2D三角形 三角形索引;
	C_线扫描包围体 包围体(1.0/10.0);

	包围体.f_构建包围层(线段);

	int32 采样层数 = 300;
	const float32 采样高度 = 1.0f/采样层数;
	float32 步进 = 0;

	std::vector<S_2D扫描交点> 上一层交点;
	for (uint32 i = 0; i < 采样层数; ++i) {
		auto 采样顶点 = 包围体.f_扫描(步进, 采样高度);
		步进 += 采样高度;


		if (采样顶点.size() > 1) {
			uint32 当前采样数量 = 采样顶点.size() & 0xfffffffe;

			uint32 上一层交点数量 = 上一层交点.size() & 0xfffffffe;;
			if (上一层交点数量) {
				assert(上一层交点数量 <= 三角形索引.point.size());
				
				uint32 三角形索引偏移_层0 = 三角形索引.point.size() - 上一层交点数量;
				uint32 三角形索引偏移_层1 = 三角形索引.point.size();
				uint32 当前层偏移ID = 0;

				上一层交点数量 = min(上一层交点数量, 当前采样数量);
				for (uint32 k = 0; k < 上一层交点数量; k += 2) {
					
					uint32 上层边ID = 上一层交点[k + 1].边ID;
					//uint32 当前边ID = 上一层交点[k + 1].边ID;

					if (上层边ID == 采样顶点[当前层偏移ID + 1].边ID) {
						三角形索引.index.push_back(三角形索引偏移_层0 + k);
						三角形索引.index.push_back(三角形索引偏移_层0 + k + 1);
						三角形索引.index.push_back(三角形索引偏移_层1 + 当前层偏移ID);

						三角形索引.index.push_back(三角形索引偏移_层0 + k + 1);
						三角形索引.index.push_back(三角形索引偏移_层1 + 当前层偏移ID);
						三角形索引.index.push_back(三角形索引偏移_层1 + 当前层偏移ID + 1);

						当前层偏移ID += 2;
					}
					else {
						while (当前层偏移ID < 当前采样数量) {
							
							三角形索引.index.push_back(三角形索引偏移_层0 + k);
							三角形索引.index.push_back(三角形索引偏移_层1 + 当前层偏移ID);
							三角形索引.index.push_back(三角形索引偏移_层1 + 当前层偏移ID + 1);

							if (上层边ID == 采样顶点[当前层偏移ID++].边ID) {
								break;
							}
						}
						
						三角形索引.index.push_back(三角形索引偏移_层0 + k);
						三角形索引.index.push_back(三角形索引偏移_层1 + 当前层偏移ID);
						三角形索引.index.push_back(三角形索引偏移_层0 + k + 1);

					}
				}
			}

			for (uint32 k = 0; k < 当前采样数量; ++k) {
				三角形索引.point.push_back(采样顶点[k].交点);
			}

			if(采样顶点.size() > 当前采样数量) 采样顶点.pop_back();
			上一层交点 = 采样顶点;
		}
		else {
			上一层交点.clear();
		}


	}
	
	return 三角形索引;
}

std::vector<uint32> f_polygon_三角化(const std::vector<S_VNTC>& 顶点, std::vector<uint32> 索引) {
	std::vector<uint32> 新三角形顶点索引;

	vec3 normal{};

	uint32 num = 索引.size();
	for (uint32 i = 0; i < num; ++i) {
		uvec3 index = f_geometry_TriangleIndex(i, num);
		
		vec3 v0 = 顶点[索引[index.x]].vert;
		vec3 v1 = 顶点[索引[index.y]].vert;
		vec3 v2 = 顶点[索引[index.z]].vert;

		normal += f_geometry_TriangleNormal(v0, v1, v2);
	}

	normal = normalize(normal);

	///for (auto it = 新顶点索引.begin(); it != 新顶点索引.end(); ) {
	for ( ; 索引.size() > 2; ) {
		
		float32 minD = 1e+8;
		uint32 minIndex = -1;
		num = 索引.size();

		for (uint32 i = 0; i < num; ++i) {
			uvec3 index = f_geometry_TriangleIndex(i, num);
			
			vec3 v0 = 顶点[索引[index.x]].vert;
			vec3 v1 = 顶点[索引[index.y]].vert;
			vec3 v2 = 顶点[索引[index.z]].vert;

			

			float32 d = dot(v1 - v0, v1 - v2);
			if (d < minD) {
				vec3 cn = f_geometry_TriangleNormal(v0, v1, v2);
				if(dot(cn, normal) < 0) continue;

				minD = d;
				minIndex = i;
			}
		}

		if (minIndex != -1) {
			uvec3 index = f_geometry_TriangleIndex(minIndex, num);

			新三角形顶点索引.push_back(索引[index.x]);
			新三角形顶点索引.push_back(索引[index.y]);
			新三角形顶点索引.push_back(索引[index.z]);

			索引.erase(索引.begin() + index.y);
		}
		else {
			新三角形顶点索引.push_back(索引[0]);
			新三角形顶点索引.push_back(索引[1]);
			新三角形顶点索引.push_back(索引[2]);
			索引.clear();
		}
	}

    return 新三角形顶点索引;
}

std::vector<uint32> f_polygon_三角化(const std::vector<S_VNTC>& 顶点, t_面顶点索引& 索引) {
	std::vector<uint32> 新索引;
	新索引.reserve(索引.size() * 2);

	for (auto& e : 索引) {
		auto indexs = f_polygon_三角化(顶点, e);
		新索引.insert(新索引.end(), indexs.begin(), indexs.end());
	}
	return 新索引;
}

std::vector<uvec2> f_polygon_构建边(const std::vector<std::vector<uint32>>& 索引) {
	std::vector<uvec2> 新索引;

	for (auto& e : 索引) {
		
		uint32 num = e.size();
		for (uint32 i = 0; i < num; ++i) {
			uvec2 r = {e[i], e[(i + 1) % num]};

			新索引.push_back({min_u32(r.x, r.y), max_u32(r.x,r.y)});
		}
	}

	std::sort(新索引.begin(), 新索引.end(), [&](const uvec2& a, const uvec2& b){
		if ( (uint64(a.x)<<32 | (a.y)) > (uint64(b.x)<<32 | (b.y)) ) {
			return true;
		}
		return false;
	});

	auto last = std::unique(新索引.begin(), 新索引.end(), [&](const uvec2& a, const uvec2& b) {
		if ( (uint64(a.x)<<32 | (a.y)) == (uint64(b.x)<<32 | (b.y)) ) {
			return true;
		}
		return false;
		
	});
	新索引.erase(last, 新索引.end());


	return 新索引;
}

void f_polygon_构建边(S_多边形* polygon) {
	uint32 num = polygon->m_面.size();

	t_面顶点索引 中间索引(num);
	for (uint32 i = 0; i < num; ++i) {
		中间索引[i] = polygon->m_面[i]->vertIndex;
	}

	polygon->m_边 = f_polygon_构建边(中间索引);

}

void f_polygon_构建多边形顶点关系(S_多边形* polygon) {
	polygon->m_顶点关联边.clear();
	polygon->m_顶点关联边.resize(polygon->m_顶点.size());

	uint32 index = 0;
	for (auto& e : polygon->m_边) {
		polygon->m_顶点关联边[e.x].push_back(index);
		polygon->m_顶点关联边[e.y].push_back(index);
		++index;
	}
	//polygon->m_顶点关联边;
}

void f_polygon_构建面与顶点关联(S_多边形* polygon) {
	polygon->m_顶点关联面.clear();
	polygon->m_顶点关联面.resize(polygon->m_顶点.size());

	
	uint32 faceIndex = 0;
	for (auto& e : polygon->m_面) {
		for (const auto& i : e->vertIndex) {
			polygon->m_顶点关联面[i].push_back(faceIndex);
		}

		++faceIndex;
	}
}

void f_polygon_计算面法线(S_多边形* polygon) {
	uint32 num = polygon->m_面.size();

#pragma omp parallel for schedule(dynamic, 512)
	for (int32 i = 0; i < num; ++i) {
		auto& e = polygon->m_面[i];
	//for (auto& e : polygon->m_面) {
		vec3 normal{};

		int32 vNum = e->vertIndex.size() - 1;
		if (vNum > 0) {
			for (int32 i = 0; i < vNum; i += 2) {
				vec3 v0 = polygon->m_顶点[e->vertIndex[i]];
				vec3 v1 = polygon->m_顶点[e->vertIndex[(i + 1)%3]];
				vec3 v2 = polygon->m_顶点[e->vertIndex[(i + 2)%3]];
				normal += f_surface_FaceNormal(v0, v1, v2);
			}
			normal /= vNum;
		}
		
		e->面法线 = normal;
	}
}

void f_polygon_计算光滑法线(S_多边形* polygon) {
	uint32 num = polygon->m_顶点.size();
	polygon->m_法线.resize(num);

	for (uint32 i = 0; i < num; ++i) {
		vec3 co1 = polygon->m_顶点[i];

		vec3 normal{};
		for (auto& e : polygon->m_顶点关联面[i]) {
			normal += polygon->m_面[e]->面法线;
		}
		polygon->m_法线[i] = normal / polygon->m_顶点关联面[i].size();
	}
}


const uint8* f_ob_Load多边形(S_多边形* polygon, const uint8* 下一次读取数据指针) {
	bool 是否压缩 = false;
	下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 是否压缩);

	下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, polygon->m_顶点, 是否压缩);
	下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, polygon->m_法线, 是否压缩);
	下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, polygon->m_边, 是否压缩);
	下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, polygon->m_UV, 是否压缩);

	uint32 面数量 = 0;
	下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 面数量);

	polygon->m_面.reserve(面数量);
	for (uint32 i = 0; i < 面数量; ++i) {
		S_面* 面 = new S_面(nullptr);

		下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, 面->vertIndex, 是否压缩);
		下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, 面->uvIndex, 是否压缩);
		下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, 面->edge, 是否压缩);

		下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 面->面中心);
		下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 面->面法线);
		下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 面->材质槽);
		下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 面->面平直);

		polygon->m_面.emplace_back(面);
	}

	return 下一次读取数据指针;
}

void f_ob_Save多边形(const S_多边形* polygon, S_UI8Array* 块, bool 是否压缩) {
	f_文件块_写数据块(块, 是否压缩);


	f_文件块_写序列数据块(块, polygon->m_顶点, 是否压缩);
	f_文件块_写序列数据块(块, polygon->m_法线, 是否压缩);
	f_文件块_写序列数据块(块, polygon->m_边, 是否压缩);
	f_文件块_写序列数据块(块, polygon->m_UV, 是否压缩);

	uint32 面数量 = polygon->m_面.size();
	f_文件块_写数据块(块, 面数量);

	for (uint32 i = 0; i < 面数量; ++i) {
		S_面* 面 = polygon->m_面[i];
		f_文件块_写序列数据块(块, 面->vertIndex, 是否压缩);
		f_文件块_写序列数据块(块, 面->uvIndex, 是否压缩);
		f_文件块_写序列数据块(块, 面->edge, 是否压缩);

		f_文件块_写数据块(块, 面->面中心);
		f_文件块_写数据块(块, 面->面法线);
		f_文件块_写数据块(块, 面->材质槽);
		f_文件块_写数据块(块, 面->面平直);
	}
	
}


void f_surface_多边形生成网格(S_多边形* 多边形, S_Mesh* me, S_Mesh* edge) {
	std::vector<S_VNTC> 顶点;
	std::vector<uint32> 索引;

	auto face = 多边形->m_面.data();
	auto vert = 多边形->m_顶点.data();
	auto normal = 多边形->m_法线.data();
	

	uint32 num = 多边形->m_顶点.size();

	顶点.resize(num);
	float32 color = glsl_RGBAToFloat({255,255,255,255});

	for (uint32 i = 0; i < num; ++i) {
		顶点[i] = {vert[i], normal[i], {0,0, color}};
	}


	num = 多边形->m_面.size();

	t_面顶点索引 中间索引(num);
	for (uint32 i = 0; i < num; ++i) {
		中间索引[i] = 多边形->m_面[i]->vertIndex;
	}
	索引 = f_polygon_三角化(顶点, 中间索引);


	f_me_fill顶点(me, 顶点);
	f_me_fill索引(me, 索引);

	if (edge) {
		f_me_fill索引(edge, 多边形->m_边);
	}
	
}





